WPF Фильтрующие колонки Datagrid Combobox - PullRequest
0 голосов
/ 22 октября 2018

Первое размещение.Я новичок в C # и WPF.Я потратил более 15 часов, пытаясь выяснить это, и вместо этого собираюсь выйти и начать заново с Windows Forms.У меня есть DataGrid с (в настоящее время) тремя столбцами, но для этого важны только два, тип и подтип.У меня есть примерно 15 типов, заполняемых из файла XML, и у каждого есть 2-15 подтипов.Я пытаюсь отфильтровать (или заполнить) второй столбец на основе того, что было выбрано в первом.

Я пытался использовать DynamicResource во втором столбце, но он перезаписывается в следующей строке и очищает выбор первой строки.Я не понимаю Bindings достаточно хорошо, чтобы знать, как сделать их конкретными.Я создал список и коллекцию на стороне C #, которая заполняется каждым подтипом выбранного типа (и другой парой, которая заполняется для каждого возможного типа, и даже встраивает коллекцию подтипов в мою коллекцию типов), но я могу:не могу понять, как получить любой из этих элементов в поле со списком элементов второго столбца, не отображая их в каждой строке.

XAML:

 <DataGridComboBoxColumn Header="Type"
                            ItemsSource="{DynamicResource UnitTypeSource}"
                            SelectedValuePath="TypeString"
                            SelectedItemBinding="{Binding Path=TypeString, NotifyOnTargetUpdated=True}"
                            DisplayMemberPath="TypeString"
                            x:Name="colTypeUnit"/>
                        <DataGridTemplateColumn Header="Subtype">
                            <DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                    <ComboBox
                                        ItemsSource="{Binding DataContext.AllSubtypes, RelativeSource={RelativeSource AncestorType=local:MainWindow}}"
                                        DisplayMemberPath="Name"
                                        />
                                </DataTemplate>
                            </DataGridTemplateColumn.CellTemplate>
                        </DataGridTemplateColumn>

Буду признателен за любую помощь или даже просто ссылкукак это должно работать.

1 Ответ

0 голосов
/ 23 октября 2018

Работа с DataGrid и ComboBoxes может быстро усложниться, поэтому давайте сделаем один шаг за раз с некоторыми объяснениями между ними.Я дал вам полные классы для кода во фрагментах.

Для начала я буду придерживаться модели MVVM и использовать модель-view-viewmmodel для привязки данных к DataGrid.Модель представления будет содержать списки значений Type и SubType, а также список строк.Класс модели для нашей строки я назову TypeModel:

public class TypeModel
{
    public string Type { get; set; }
    public string SubType { get; set; }
}

Я не знаю, как вы определите, что SubType действительно для данного Type, но для этого примера я буду использоватьсловарь для настройки отношений в модели представления.

Таким образом, наша модель представления может выглядеть примерно так:

public class MainWindowViewModel
{
    public ObservableCollection<TypeModel> Collection { get; set; }

    public ObservableCollection<string> Type { get; set; }

    public Dictionary<string, List<string>> SubTypeCollection { get; set; }

    public MainWindowViewModel()
    {
        Collection = new ObservableCollection<TypeModel>();
        TypeCollection = new ObservableCollection<string>()
        {
            "Type 1","Type 2","Type 3"
        };

        SubTypeCollection = new Dictionary<string, List<string>>()
        {
            {
                TypeCollection[0], new List<string>()
                {
                    "Type 1 - Sub type 0",
                    "Type 1 - Sub type 1"
                }
            },
            {
                TypeCollection[1], new List<string>()
                {
                    "Type 2 - Sub type 0",
                    "Type 2 - Sub type 1",
                    "Type 2 - Sub type 2",
                    "Type 3 - Sub type 3",
                }
            },
            {
                TypeCollection[2], new List<string>()
                {
                    "Type 3 - Sub type 0",
                    "Type 3 - Sub type 1",
                    "Type 3 - Sub type 2",
                }
            }
        };
    }
}

Теперь давайте настроим наше (начальное) представление (добавим к этому позже):

<Window x:Class="WpfApp1.MainWindow"
        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:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow"
        Width="600"
        Height="500">
    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>
    <Grid>
        <DataGrid
            AutoGenerateColumns="False"
            ItemsSource="{Binding Collection}">
            <DataGrid.Columns>
                <DataGridComboBoxColumn
                    Header="Type"
                    SelectedItemBinding="{Binding Type, UpdateSourceTrigger=PropertyChanged}"> <!-- property changed so we get the change right after we select-->
                    <DataGridComboBoxColumn.ElementStyle>
                        <Style
                            TargetType="ComboBox">
                            <Setter
                                Property="ItemsSource"
                                Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.TypeCollection}" />
                        </Style>
                    </DataGridComboBoxColumn.ElementStyle>
                    <DataGridComboBoxColumn.EditingElementStyle>
                        <Style
                            TargetType="ComboBox">
                            <Setter
                                Property="ItemsSource"
                                Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.TypeCollection}" />
                        </Style>
                    </DataGridComboBoxColumn.EditingElementStyle>
                </DataGridComboBoxColumn>

            <DataGridComboBoxColumn
                Header="Sub Type"
                SelectedItemBinding="{Binding SubType}">
                <!-- How do we bind to the ItemSource based on the selected type?-->
            </DataGridComboBoxColumn>
        </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

Итак, ваш фундаментальный вопрос заключается в том, как заполнить этот закомментированный раздел.

Вероятно, есть много способов сделать это - самым простым в моем уме было бы использоватьIMultiValueConverter Это принимает две привязки:

  1. выбранная Type строка
  2. словарь TypeCollection

Так что этот класс будет выглядеть такэто (вы действительно можете использовать это для всех преобразований string в list<string>):

public class TypeToSubTypesConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        if (values == null) return null;

        if (values[0] == null || values[0] == DependencyProperty.UnsetValue) return null;
        var type = values[0].ToString();

        if (values[1] == null || values[1] == DependencyProperty.UnsetValue) return null;
        var subTypeList = values[1] as Dictionary<string, List<string>>;

        if (subTypeList == null) return null;


        return subTypeList[type];

    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        return null;
    }
}

Теперь последним шагом будет:

  1. Добавить ресурс конвертера вview
  2. Добавьте мультисвязывание к свойству value каждого setter для ItemsSource второгоПоле со списком

Итак, полный .xaml выглядит так:

<Window x:Class="WpfApp1.MainWindow"
        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:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow"
        Width="600"
        Height="500">
    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>
    <Window.Resources>
        <local:TypeToSubTypesConverter
            x:Key="TypeToSubTypesConverter" />
    </Window.Resources>
    <Grid>
        <DataGrid
            AutoGenerateColumns="False"
            ItemsSource="{Binding Collection}">
            <DataGrid.Columns>
                <DataGridComboBoxColumn
                    Header="Type"
                    SelectedItemBinding="{Binding Type, UpdateSourceTrigger=PropertyChanged}"> <!-- property changed so we get the change right after we select-->
                    <DataGridComboBoxColumn.ElementStyle>
                        <Style
                            TargetType="ComboBox">
                            <Setter
                                Property="ItemsSource"
                                Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.TypeCollection}" />
                        </Style>
                    </DataGridComboBoxColumn.ElementStyle>
                    <DataGridComboBoxColumn.EditingElementStyle>
                        <Style
                            TargetType="ComboBox">
                            <Setter
                                Property="ItemsSource"
                                Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.TypeCollection}" />
                        </Style>
                    </DataGridComboBoxColumn.EditingElementStyle>
                </DataGridComboBoxColumn>

            <DataGridComboBoxColumn
                Header="Sub Type"
                SelectedItemBinding="{Binding SubType, UpdateSourceTrigger=PropertyChanged}"> <!-- property changed so we get the change right after we select-->
                <DataGridComboBoxColumn.ElementStyle>
                    <Style
                        TargetType="ComboBox">
                        <Setter
                            Property="ItemsSource">
                            <Setter.Value>
                                <MultiBinding
                                    Converter="{StaticResource ResourceKey=TypeToSubTypesConverter}">
                                    <Binding
                                        Path="Type" />
                                    <Binding
                                        Path="DataContext.SubTypeCollection"
                                        RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}"/>
                                </MultiBinding>
                            </Setter.Value>
                        </Setter>
                    </Style>
                </DataGridComboBoxColumn.ElementStyle>
                <DataGridComboBoxColumn.EditingElementStyle>
                    <Style
                        TargetType="ComboBox">
                        <Setter
                            Property="ItemsSource">
                            <Setter.Value>
                                <MultiBinding
                                    Converter="{StaticResource ResourceKey=TypeToSubTypesConverter}">
                                    <Binding
                                        Path="Type" />
                                    <Binding
                                        Path="DataContext.SubTypeCollection"
                                        RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}" />
                                </MultiBinding>
                            </Setter.Value>
                        </Setter>
                    </Style>
                </DataGridComboBoxColumn.EditingElementStyle>
            </DataGridComboBoxColumn>
        </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...