MultiBinding с двумя комбинированными списками в разных DataContexts - PullRequest
0 голосов
/ 24 октября 2018

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

<DataGrid x:Name="FilterSelection" HorizontalAlignment="Stretch">

    <DataGrid.Resources>
        <DataTemplate x:Key="EntityComboboxTemp">
            <ComboBox x:Name="EntityCombobox"
                ItemsSource="{Binding DataContext.FilterVehicleEntities, RelativeSource={RelativeSource AncestorType=local:ExportView}}">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="SelectionChanged">
                        <i:InvokeCommandAction 
                            Command="{Binding DataContext.SelectedEntityCommand, RelativeSource={RelativeSource AncestorType=local:ExportView}}"
                            CommandParameter="{Binding ElementName=EntityCombobox, Path=SelectedItem}">
                        </i:InvokeCommandAction>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </ComboBox>
        </DataTemplate>


        <DataTemplate x:Key="AttributeComboboxTemp">
            <ComboBox x:Name="AttributeCombobox"
                ItemsSource="{Binding DataContext.FilterAttributes, RelativeSource={RelativeSource AncestorType=local:ExportView}}">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="SelectionChanged">
                        <i:InvokeCommandAction 
                            Command="{Binding DataContext.SelectedAttributeCommand, RelativeSource={RelativeSource AncestorType=local:ExportView}}">
                            <i:InvokeCommandAction.CommandParameter>
                                <MultiBinding Converter="{conv:FilterMultipleConverter}">
                                    <Binding ElementName="EntityCombobox" Path="SelectedItem"/>
                                    <Binding ElementName="AttributeCombobox" Path="SelectedItem"/>
                                </MultiBinding>
                            </i:InvokeCommandAction.CommandParameter>
                        </i:InvokeCommandAction>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </ComboBox>
        </DataTemplate>
    </DataGrid.Resources>


    <DataGrid.Columns>
        <DataGridTemplateColumn Header="Entity" CellTemplate="{StaticResource EntityComboboxTemp}" />
        <DataGridTemplateColumn Header="Entity Attribute" CellTemplate="{StaticResource AttributeComboboxTemp}"/>
    </DataGrid.Columns>
</DataGrid>

Проблема заключается в многократном связывании второго комбинированного списка, а именно строки:

Binding ElementName="EntityCombobox" Path="SelectedItem"/>

, которая должна связать выбранный элемент первого комбинированного списка со вторым комбинированным списком в качестве параметра команды.Но я всегда получаю ошибку привязки данных, что EntityCombobox неизвестен.Как я могу установить DataContext для этой привязки, это вообще возможно?

Ответы [ 2 ]

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

A ComboBox в DataTemplate не может ссылаться на ComboBox, который определен где-то еще с использованием привязки ElementName, поскольку они не находятся в той же именной области .

Что вам нужно сделать, это связать свойство SelectedItem EntityCombobox со свойством источника, а затем связать свойство CommandParameter другого ComboBox с тем же свойством источника.Чтобы это работало, класс, в котором определено исходное свойство, должен реализовывать интерфейс INotifyPropertyChanged и выдавать уведомления об изменениях, и оба ComboBoxes должны также использовать один и тот же DataContext.

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

Мое предложение - не делать так, по вашему мнению.Я бы порекомендовал сделать эту логику в ViewModel для DataGrid.

Для начала я бы создал модель представления для хранения выбранных вами фильтров.

Пример: (см. Комментарии, гдедобавьте логику для изменений выбора)

public class FilterViewModel
{
    private string _vehicleEntity;
    public string VehicleEntity
    {
        get { return _vehicleEntity; }
        set
        {
            _vehicleEntity = value;
            //OnPropertyChanged() if you want
        }
    }

    private string _attribute;
    public string Attribute
    {
        get { return _attribute; }
        set
        {
            _attribute = value;
            //Add logic here to determine what to do with both Attribute and VehicleEntity
            //OnPropertyChanged() if you want
        }
    }
}

Затем настройте ViewModel вашего общего представления, чтобы он содержал коллекцию FilterModel вместе со списком опций транспортного средства и опций атрибута.

Пример:

public class MainWindowViewModel
{
    public ObservableCollection<FilterViewModel> Rows { get; }
    public ObservableCollection<string> FilterVehicleEntities { get; }
    public ObservableCollection<string> FilterAttributes { get; set; }

    public MainWindowViewModel()
    {
        Rows = new ObservableCollection<FilterViewModel>();

        FilterVehicleEntities = new ObservableCollection<string>()
        {
            "Vehicle 1",
            "Vehicle 2",
            "Vehicle 3",
        };

        FilterAttributes = new ObservableCollection<string>()
        {
            "Attribute 1",
            "Attribute 2",
            "Attribute 3",
        };
    }
}

Затем сделайте ваш вид менее сложным, просто связав выбор со свойствами.Затем вы получите уведомление об изменениях выбора, как только свойство обновится (как отмечено в комментариях к FilterViewModel).

Пример (полный 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>
    <Grid>
        <DataGrid
            AutoGenerateColumns="False"
            ItemsSource="{Binding Rows}">
            <DataGrid.Columns>
                <DataGridComboBoxColumn
                    Header="Entity"
                    SelectedItemBinding="{Binding VehicleEntity, 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.FilterVehicleEntities}" />
                        </Style>
                    </DataGridComboBoxColumn.ElementStyle>
                    <DataGridComboBoxColumn.EditingElementStyle>
                        <Style
                            TargetType="ComboBox">
                            <Setter
                                Property="ItemsSource"
                                Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.FilterVehicleEntities}" />
                        </Style>
                    </DataGridComboBoxColumn.EditingElementStyle>
                </DataGridComboBoxColumn>

                <DataGridComboBoxColumn
                    Header="Entity Attribute"
                    SelectedItemBinding="{Binding Attribute, 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.FilterAttributes}" />
                        </Style>
                    </DataGridComboBoxColumn.ElementStyle>
                    <DataGridComboBoxColumn.EditingElementStyle>
                        <Style
                            TargetType="ComboBox">
                            <Setter
                                Property="ItemsSource"
                                Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.FilterAttributes}" />
                        </Style>
                    </DataGridComboBoxColumn.EditingElementStyle>
                </DataGridComboBoxColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...