Как установить флажки в XAML? - PullRequest
0 голосов
/ 02 января 2019

У меня есть список объектов как ObservableCollection<MyObject>. Я уже могу отобразить свойство name этих объектов в выпадающем списке, используя XAML в DataGrid.

Теперь у меня есть другой объект AnotherObject, у которого есть свойство, которое определено как список строк, и каждый элемент этого списка является name свойством MyObject, упомянутым выше.

В поле со списком я хочу отобразить свойство MyObject.name, перед которым стоит флажок. Допустим, в флажке 30 элементов, а экземпляр AnotherObject.names содержит три из них. Теперь я хочу установить флажки для тех элементов, которые равны трем элементам в AnotherObject.names.

Как мне этого добиться?

Код:

MyObjectViewModel.cs:

public class MyObjectViewModel
{
    private MyObject _myObject;

    public MyObjectViewModel(MyObject myObject)
    {
        this._myObject = myObject;
    }

    public MyObject MyObject
    {
        get
        {
            return _myObject;
        }
        set
        {
            _myObject = value;
        }
    }

    public string Name
    {
        get { return _myObject.Name;  }
        set
        {
            _myObject.Name = value;
        }
    }

    public override string ToString()
    {
        return Name;
    }
}

AnotherObjectRowViewmodel.cs:

public class AnotherObjectRowViewModel : INotifyPropertyChanged
{
    private AnotherObject _anotherObject;
    private ObservableCollection<MyObjectViewModel> _myObjects;

    public AnotherObjectRowViewModel(AnotherObject anotherObject, ObservableCollection<MyObjectViewModel> myObjects)
    {
        this._anotherObject = anotherObject;
        this._myObjects = myObjects;
    }

    public AnotherObject AnotherObject
    {
        get
        {
            return _anotherObject;
        }
        set
        {
            this._anotherObject = value;
        }
    }

    public string Name
    {
        get { return _anotherObject.Name; }
        set { _anotherObject.Name = value; }
    }

    public ObservableCollection<MyObjectViewModel> MyObjects {
        get
        {
            return this._myObjects;
        }
        set
        {
            _myObjects = value;
        }
    }

    event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
    {
        add
        {
            //throw new NotImplementedException();
        }

        remove
        {
            //throw new NotImplementedException();
        }
    }
}

Вот что я попробовал в файле XAML:

<DataGridTemplateColumn x:Name="NamesColumn" Header="Names">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <Grid>
                <ComboBox Name="Name" DataContext="{Binding}" ItemsSource="{Binding Path=myObjects}" IsEditable="True" IsReadOnly="True" 
                          VerticalAlignment="Center" SelectionChanged="OnDetailParamsSelectionChanged" >
                    <ComboBox.ItemTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal">
                                <CheckBox x:Name="chbNames" Width="20" VerticalAlignment="Center" Checked="OnChbDetailParamsCheckBoxChecked" Unchecked="OnChbDetailParamsCheckBoxChecked"></CheckBox>
                                <TextBlock DataContext="{Binding Path=MyObject}" Text="{Binding Path=Name, Converter={StaticResource StringListConverter}}" VerticalAlignment="Center" />
                            </StackPanel>
                        </DataTemplate>
                    </ComboBox.ItemTemplate>
                </ComboBox>
            </Grid>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

Пример: В выпадающем списке содержится список из 30 имен (Name1, ..., Name30);

AnotherObject.names: {Name1, Name2, Name4, Name7};

В выпадающем списке выбранными элементами должны быть Имя1, Имя2, Имя4, Имя7. Все остальные пункты должны остаться не выбранными.

Обновление 2019-01-06: Это означает, что ItemsSource = {Binding} в Combobox равен MyObject , но отмеченные элементы должны храниться в AnotherObject . Вот почему я получаю это исключение всякий раз, когда ставлю галочку:

System.Windows.Data Error: 40 : BindingExpression path error: 'xxx' property not found on 'object' ''MyObjectViewModel' (HashCode=34649765)'. BindingExpression:Path=xxx.DetailParams; DataItem='MyObjectViewModel' (HashCode=34649765); target element is 'CheckBox' (Name='chbDetailParams'); target property is 'IsChecked' (type 'Nullable`1')

Мой XAML содержит следующий фрагмент кода в соответствии с IsItemsSelectedConverter :

<UserControl.Resources>
    <ctb:IsItemSelectedConverter x:Key="IsItemSelectedConverter"/>
</UserControl.Resources>

Флажки IsChecked свойство выглядит следующим образом:

IsChecked="{Binding Path=Names, Mode=TwoWay, Converter={StaticResource IsItemSelectedConverter}}"

но это не работает. При отладке этого кода IsItemsSelectedConverter никогда не используется.

Ответы [ 2 ]

0 голосов
/ 02 января 2019

Создайте IsItemSelectedConverter и передайте список объектов из вашей модели данных. Реализуйте IValueConverter в новом классе и привяжите свойство IsChecked для каждого флажка к двум вещам: значение должно быть текущим элементом, а параметр должен быть списком элементов. Преобразователь должен определить, находится ли текущий элемент в списке элементов, и вернуть соответствующий логический параметр.

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

Мой IsItemSelectedConverter выглядит так:

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {

            if (value is MyObjectViewModel objectViewModel && parameter is AnotherObjectRowViewModel anotherObjectRowViewModel)
            {
                return anotherObjectRowViewModel.MyObjects.Contains(objectViewModel);
            }
            return false;
        }

На XAML мой код CheckBox выглядит так: <CheckBox IsChecked="{Binding Mode=OneWay, Converter={StaticResource converter}, ConverterParameter={StaticResource viewModel} }" />

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

0 голосов
/ 02 января 2019

Создайте логическое свойство в модели представления MyObject, то есть в MyObjectViewModel, которое будет возвращать значение, если Name находится в списке имен в AnotherObject.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...