Предложения по синхронизации списков в Silverlight - PullRequest
2 голосов
/ 06 сентября 2010

Мы создаем бизнес-приложение (Silverlight 4) в нашей компании, в котором мы в некоторых из наших представлений используем функциональность для синхронизации двух списков какого-либо рода.

В настоящий момент мы более точныс использованием двух списков (один источник и одна цель) и двух кнопок (один добавить и один удалить).И исходный список, и целевые списки привязаны к коллекциям с одинаковым типом данных.

Пользователь может выбрать один или несколько элементов в исходном списке и нажать кнопку добавления, чтобы элементы были перемещены в целевой список.(т.е. элементы удаляются из источника и добавляются к цели).

Аналогично, пользователь может выбрать один или несколько элементов в списке целей и нажать кнопку удаления, чтобы элементы были перемещены из цели обратно в источник.list.

Существует также возможность добавить правило проверки, согласно которому пользователь должен добавить хотя бы один элемент в целевой список.

Довольно просто ...

До сих пор мы используем наш собственный пользовательский элемент управления, который включает в себя эти 4 элемента управления (2 списка и 2 кнопки) и логику для синхронизации списков.Свойства зависимостей используются для привязки исходной и целевой коллекций.

Теперь к проблеме.Теперь наш клиент хочет, чтобы наш пользовательский контроль был более гибким.Они хотят иметь произвольное количество столбцов как в исходном, так и в целевом списке (т. Е. Исходный список может иметь разные столбцы и количество столбцов, отличное от целевого списка).Клиент также хочет иметь возможность сортировки по любому столбцу.

Моей первой мыслью было заменить вместо этого поле списка на сетку данных.Но потом я понял, что не знаю, как простым способом позволить потребителю (разработчику) определить его или ее столбцы и привязки.Это может быть моим ограниченным знанием SL.Может быть, пользовательский элемент управления не подходит?

Буду признателен за любую помощь.Прямо сейчас мы снова и снова применяем одну и ту же логику в наших взглядах, и это не так.Должен быть какой-то способ сделать этот компонент многократного использования, который прост в использовании.

Спасибо!

Ответы [ 3 ]

1 голос
/ 06 сентября 2010

«Сетевая версия» ответа:

(см. Список версий ниже)

Поскольку вопрос изменился (уточнил), я добавляю новый ответ. Первый по-прежнему полезен для тех, кому нужны только списки, поэтому я оставлю его там.

Чтобы сделать то же самое с сетками, вы не предоставляете шаблоны , так как столбцы сетки данных не шаблонизированы (это списки элементов управления, которые могут быть индивидуально настроены) . alt text

Вместо этого вы выставляете коллекции столбцов левой и правой сетки в качестве свойств и просто устанавливаете свойства LeftColumns и RightColumns элемента управления на родительской странице. Единственная хитрость заключается в том, что коллекции столбцов данных не имеют установщика , поэтому необходимо обновить элементы коллекций сетки из новых коллекций свойств:

Код теперь:

using System.Collections.ObjectModel;
using System.Windows.Controls;

namespace SilverlightApplication1
{
    public partial class GridSelectionControl : UserControl
    {
        public GridSelectionControl()
        {
            InitializeComponent();
        }

        public ObservableCollection<DataGridColumn> LeftColumns
        {
            get
            {
                return leftDataGrid.Columns;
            }
            set
            {
                leftDataGrid.Columns.Clear();
                foreach (var col in value)
                {
                    leftDataGrid.Columns.Add(col);
                }
            }
        }

        public ObservableCollection<DataGridColumn> RightColumns
        {
            get
            {
                return rightDataGrid.Columns;
            }
            set
            {
                rightDataGrid.Columns.Clear();
                foreach (var col in value)
                {
                    rightDataGrid.Columns.Add(col);
                }
            }
        }
    }
}

Теперь Xaml элемента управления:

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" x:Class="SilverlightApplication1.GridSelectionControl"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <sdk:DataGrid x:Name="leftDataGrid" Margin="10" AutoGenerateColumns="False"/>
        <sdk:DataGrid x:Name="rightDataGrid" Margin="10" Grid.Column="2" AutoGenerateColumns="False"/>
        <StackPanel Grid.Column="1" Orientation="Vertical">
            <Button Content="Add &gt;" Height="23" HorizontalAlignment="Left" Width="75" Margin="10" />
            <Button Content="&lt; Remove" Height="23" HorizontalAlignment="Left" Width="75" Margin="10" />
        </StackPanel>

    </Grid>
</UserControl>

Xaml тестовой страницы (которая определяет столбцы) теперь:

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:SilverlightApplication1" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
    mc:Ignorable="d"
    x:Class="SilverlightApplication1.TestGridSelectionControl"
    d:DesignWidth="640" d:DesignHeight="480">

    <Grid x:Name="LayoutRoot">
        <local:GridSelectionControl x:Name="SelectionControl">
            <local:GridSelectionControl.LeftColumns>
                <sdk:DataGridCheckBoxColumn Header="Machine?" Binding="{Binding IsMachine}"/>
                <sdk:DataGridTextColumn Header="First Name" Binding="{Binding FirstName}"/>
                <sdk:DataGridTextColumn Header="Last Name" Binding="{Binding LastName}"/>
            </local:GridSelectionControl.LeftColumns>
            <local:GridSelectionControl.RightColumns>
                <sdk:DataGridCheckBoxColumn Header="Machine?" Binding="{Binding IsMachine}"/>
                <sdk:DataGridTextColumn Header="First Name" Binding="{Binding FirstName}"/>
                <sdk:DataGridTextColumn Header="Last Name" Binding="{Binding LastName}"/>
            </local:GridSelectionControl.RightColumns>
        </local:GridSelectionControl>
    </Grid>
</UserControl>

И тестовый код теперь:

using System.Collections.ObjectModel;
using System.Windows.Controls;

namespace SilverlightApplication1
{
    public partial class TestGridSelectionControl : UserControl
    {
        public TestGridSelectionControl()
        {
            // Required to initialize variables
            InitializeComponent();
            SelectionControl.leftDataGrid.ItemsSource = Person.People;
            SelectionControl.rightDataGrid.ItemsSource = Person.Machines;
        }

        public class Person
        {
            public string FirstName { get; set; }
            public string LastName { get; set; }
            public bool IsMachine { get; set; }

            public Person(string firstname, string lastname, bool robot)
            {
                this.FirstName = firstname;
                this.LastName = lastname;
                this.IsMachine = robot;
            }

            public static ObservableCollection<Person> People = new ObservableCollection<Person>()
                                                                {
                                                                    new Person("Tom", "Jones", false),
                                                                    new Person("Elis", "Presley", false),
                                                                    new Person("Joe", "Blogs", false)
                                                                };

            public static ObservableCollection<Person> Machines = new ObservableCollection<Person>()
                                                                {
                                                                    new Person("Marvin", "Android", true),
                                                                    new Person("Hal", "9000", true),
                                                                    new Person("B", "9", true)
                                                                };
        }
    }
}
1 голос
/ 06 сентября 2010

Поскольку вы создаете элемент управления для использования другими разработчиками, обычно лучше использовать шаблонный элемент управления, а не UserControl. В этом случае разработчики могут указать собственный шаблон для элемента управления. Однако это не так полезно, как вы могли бы быть, особенно если набор заголовков для обеих сеток одинаков.

Один из подходов, который вы можете использовать, - предоставить свойство зависимости типа DataTemplate, называемое «ListTemplate». В двух точках вашего элемента управления Xaml, где вы будете отображать списки, используйте два элемента ControlPresenter. Один с именем «SourceContent», другой с именем «TargetContent». Для обоих привязать ContentTemplate к этому новому "ListTemplate".

Кодируйте присвоение свойства Content для этих докладчиков, а затем присвойте соответствующей коллекции ItemsSource либо ItemsControl, либо DataGrid, загруженный докладчиком.

Если вы включаете простой базовый шаблон данных ListBox в качестве значения по умолчанию для свойства "ListTemplate", то под вашим контролем должно быть удобно пользоваться в его самой простой форме, но если разработчик хочет использовать DataGrid с различными столбцами, которые он может определить один в ListTemplate собственность.

Конечно, вам нужно будет написать код в вашем элементе управления, чтобы справиться со списками, которые могут быть элементами DataGrid.

0 голосов
/ 06 сентября 2010

«Версия списка» ответа

(см. Также версию сетки)

Для этого подходит пользовательский элемент управления, но вы хотите, чтобы оба списка были шаблонными, чтобы разработчик мог определитьза количество просмотров.Я предположил, что вам не нужны заголовки, поэтому застрял в списках.Приведенный ниже тестовый код приводит к следующему:

alt text

Поскольку в списках уже есть шаблоны элементов, вы действительно хотите представить их как свойства в своем пользовательском элементе управления.Затем вы можете редактировать 2 шаблона по отдельности (в приведенном ниже примере просто оба шаблона Left и Right установлены на одну и ту же панель стека FirstName / LastName, здесь вы определяете формат ваших списков):

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:SilverlightApplication1"
    mc:Ignorable="d"
    x:Class="SilverlightApplication1.TestListSelectionControl"
    d:DesignWidth="640" d:DesignHeight="480">
    <UserControl.Resources>
        <DataTemplate x:Key="DataTemplate1">
            <Grid>
                <StackPanel Orientation="Horizontal">
                    <TextBlock TextWrapping="Wrap" HorizontalAlignment="Left" VerticalAlignment="Top" Width="65" Text="{Binding FirstName}"/>
                    <TextBlock TextWrapping="Wrap" HorizontalAlignment="Left" VerticalAlignment="Top" Width="65" Text="{Binding LastName}"/>
                </StackPanel>
            </Grid>
        </DataTemplate>
    </UserControl.Resources>

    <Grid x:Name="LayoutRoot">
        <local:ListSelectionControl x:Name="SelectionControl" d:LayoutOverrides="Height" LeftItemTemplate="{StaticResource DataTemplate1}" RightItemTemplate="{StaticResource DataTemplate1}"/>
    </Grid>
</UserControl>

Пример XAML ListSelectionControl приведен ниже:

<UserControl x:Class="SilverlightApplication1.ListSelectionControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <ListBox HorizontalAlignment="Stretch" Margin="12" Name="leftListBox" VerticalAlignment="Stretch" />
        <ListBox HorizontalAlignment="Stretch" Margin="12" Name="rightListBox" VerticalAlignment="Stretch" Grid.Column="2" />
        <StackPanel Grid.Column="1" Orientation="Vertical">
            <Button Content="Add &gt;" Height="23" HorizontalAlignment="Left" Width="75" Margin="10" />
            <Button Content="&lt; Remove" Height="23" HorizontalAlignment="Left" Width="75" Margin="10" />
        </StackPanel>
    </Grid>
</UserControl>

И простой код для элемента управления:

using System.Windows;
using System.Windows.Controls;

    namespace SilverlightApplication1
    {
        public partial class ListSelectionControl : UserControl
        {
            public DataTemplate LeftItemTemplate
            {
                get
                {
                    return leftListBox.ItemTemplate;
                }

                set
                {
                    leftListBox.ItemTemplate = value;
                }
            }

            public DataTemplate RightItemTemplate
            {
                get
                {
                    return rightListBox.ItemTemplate;
                }

                set
                {
                    rightListBox.ItemTemplate = value;
                }
            }

            public ListSelectionControl()
            {
                InitializeComponent();

            }

        }
    }

И просто для завершенияНапример, это код для заполнения примера графического интерфейса:

using System.Windows.Controls;
using System.Collections.ObjectModel;

namespace SilverlightApplication1
{
    public partial class TestListSelectionControl : UserControl
    {
        public TestListSelectionControl()
        {
            // Required to initialize variables
            InitializeComponent();
            SelectionControl.leftListBox.ItemsSource = Person.People;
            SelectionControl.rightListBox.ItemsSource = Person.Machines;
        }
    }

    public class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }

        public Person(string firstname, string lastname)
        {
            this.FirstName = firstname;
            this.LastName = lastname;
        }

        public static ObservableCollection<Person> People = new ObservableCollection<Person>()
                                                                {
                                                                    new Person("Tom", "Jones"),
                                                                    new Person("Elis", "Presley"),
                                                                    new Person("Joe", "Blogs")
                                                                };

        public static ObservableCollection<Person> Machines = new ObservableCollection<Person>()
                                                                {
                                                                    new Person("Marvin", "Android"),
                                                                    new Person("Hal", "9000"),
                                                                    new Person("B", "9")
                                                                };
    }
}
...