MVVM;在标题中带有ComboBox的DataGridTextColumn,它决定了列的绑定 [英] MVVM; DataGridTextColumn with a ComboBox in the header, which determines the Binding of the Column
问题描述
我需要一个 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屋!