MVVM;在标题中带有ComboBox的DataGridTextColumn,它决定了列的绑定 [英] MVVM; DataGridTextColumn with a ComboBox in the header, which determines the Binding of the Column

查看:76
本文介绍了MVVM;在标题中带有ComboBox的DataGridTextColumn,它决定了列的绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一个 DataGrid 与一个或多个 DataGridTextColumn ,它的 Binding.Path 属性更改时,其标题中 ComboBox 的选定项目更改。这个 ComboBox ItemsSource 应该是模型中的属性列表。



但是, Path 不是 DependencyProperty ,因此无法绑定。



我在尝试回覆


I needed a DataGrid with one or more DataGridTextColumn, which its Binding.Path property change when the selected item of a ComboBox in its header changes. The ItemsSource of this ComboBox should be the list of properties in the model.

However, the Path is not a DependencyProperty and therefore cannot be bound.

I encountered this problem while I was trying to answer a vague question. In fact, I was not sure if this is what he wants and therefore, I thought I send it as a separate Q&A.

Note that if the number of properties in the Model is small, such a column can be presented in a few number of columns. However, when the number of properties increase, this might be useful.

I couldn't find any similar question. This one seems to be similar, however, does not implement MVVM.

解决方案

Assuming that the model has two properties Name and Desc:

public class Model : INotifyPropertyChanged
{
    string _desc;
    public string Desc { get { return _desc; } set { _desc = value; RaisePropertyChanged("Desc"); } }

    string _name;
    public string Name { get { return _name; } set { _name = value; RaisePropertyChanged("Name"); } }

    public event PropertyChangedEventHandler PropertyChanged;
    internal void RaisePropertyChanged(string propname)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propname));
    }
}

The view model should get a list of these properties (Items) and have a SelectedItem which indicates the current selected property. Other things are usual properties of a view model:

public class ViewModel : INotifyPropertyChanged
{
    public ViewModel()
    {
        Models = new ObservableCollection<Model>() { new Model() {Name = "aaaa", Desc = "desc1" }, new Model() { Name = "bbbbb", Desc="desc2"  } };

        Items = new ObservableCollection<PropertyInfo>(typeof(Model).GetProperties());
        SelectedItem = Items[0];
    }
    ObservableCollection<PropertyInfo> _items;
    public ObservableCollection<PropertyInfo> Items { get { return _items; } set { _items = value; RaisePropertyChanged("Items"); } }

    PropertyInfo _selectedItem;
    public PropertyInfo SelectedItem { get { return _selectedItem; } set {
            _selectedItem = value; RaisePropertyChanged("SelectedItem"); 
        } }

    ObservableCollection<Model> _models;
    public ObservableCollection<Model> Models { get { return _models; }set { _models = value; RaisePropertyChanged("Models"); } }

  public event PropertyChangedEventHandler PropertyChanged;
    void RaisePropertyChanged(string propname)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propname));
    }
}

The view needs an MultiBinding to get the selected properties value:

<DataGrid DataContext="{Binding}" ItemsSource="{Binding Models}" AutoGenerateColumns="False">
    <DataGrid.Resources>
        <local:conv1 x:Key="conv1" />
    </DataGrid.Resources>
    <DataGrid.Columns>
        <DataGridTextColumn>
            <DataGridTextColumn.Binding>
                <MultiBinding Converter="{StaticResource conv1}">
                    <Binding />
                    <Binding Path="DataContext.SelectedItem" RelativeSource="{RelativeSource AncestorType=DataGrid, Mode=FindAncestor}" />
                </MultiBinding>
            </DataGridTextColumn.Binding>
            <DataGridTextColumn.Header>
                <ComboBox DataContext="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType=DataGrid, Mode=FindAncestor}}" 
                          ItemsSource="{Binding Items}" SelectedItem ="{Binding SelectedItem, Mode=TwoWay}"/>
            </DataGridTextColumn.Header>
        </DataGridTextColumn>
    </DataGrid.Columns>
</DataGrid>

in which

public class conv1 : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        Model m = values[0] as Model;
        PropertyInfo pi = values[1] as PropertyInfo;
        if (m != null && pi != null)
        {
            return pi.GetValue(m);
        }
        return Binding.DoNothing;
    } 
    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    } 
}

and

public partial class MainWindow : Window
{ 
    public MainWindow()
    {  
        this.InitializeComponent();
        DataContext = new ViewModel(); 
    } 
}

which results in this:

这篇关于MVVM;在标题中带有ComboBox的DataGridTextColumn,它决定了列的绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆