如有不理解的地方请留言。
1.主要解决问题:DataGrid滚动条拉动导致表格数据混乱、数据双向绑定、ComboBox数据源更改后默认显示空值(设置SelectedIndex为0无效
2.解决问题
2.1DataGrid滚动条拉动导致表格数据混乱
将DataGrid中EnableRowVirtualization属性值改为False,不进行动态数据显示。
EnableRowVirtualization="False"
2.2数据双向绑定
1.绑定数据源时设置ComboBox的两个关键属性
ItemsSource="{Binding ItemList,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
2.数据源继承上INotifyPropertyChanged接口,实现接口成员方法,实现当数据源发生变化时通知控件数据源的更新
如:
public class ABC : INotifyPropertyChanged { public ABC() { } public string id; public string ID { get { return id; } set { id = value; OnPropertyChanged("ID"); } } public string des; public string Des { get { return des; } set { des = value; OnPropertyChanged("Des"); } } public string name; public string Name { get { return name; } set { name = value; OnPropertyChanged("Name"); } } protected internal virtual void OnPropertyChanged(string propertyName) { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } public event PropertyChangedEventHandler PropertyChanged; }
2.3ComboBox数据源更改后默认显示空值
ComboBox数据源更新后会执行一遍SelectionChanged事件,这时返回的SelectedIndex为-1,SelectedItem也是null;
解决方法:手动绑定SelectedIndex或SelectedItem值实现跟随数据源变化而变化(需要ComboBox数据源每项必须存在一个是否被选中的属性),我这边用的SelectedIndex。
自定义ComboxSelIndexConverter会在下面cs中贴出。
在window标签中加入:
xmlns:ValueConverter="clr-namespace:WpfTempleate.Converts"
在Window.Resources中加入:
<Window.Resources>
<ValueConverter:ComboxSelIndexConverter x:Key="ComboxSelIndexConverter"/>
</Window.Resources>
ComboBox中加入:
SelectedIndex="{Binding ItemList,Converter={StaticResource ComboxSelIndexConverter},Mode=OneWay}"
对应的Class->ComboxSelIndexConverter.cs在下面贴出。
3.描述:
xaml->DataGrid
ItemsSource="{Binding People,ElementName=root}"
其中root是当前页面的name值,绑定上下文为当前页面对象,相当于DataContext="{Binding ElementName=root}"
People是DataGrid绑定的数据源(集合)
xaml->ComboBox
ItemsSource="{Binding ItemList,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
其中ItemList是ComboBox绑定的数据源(集合)
其中UpdateSourceTrigger=PropertyChanged是表示ComboBox发生变化时触发更新数据源
贴出代码
xaml:
<DataGrid Width="500" Height="400" x:Name="dataGrid" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Visible" ItemsSource="{Binding People,ElementName=root}" GridLinesVisibility="All" BorderThickness="1,1,2,1" CanUserDeleteRows="False" CanUserAddRows="False" AutoGenerateColumns="False" EnableRowVirtualization="False"> <DataGrid.Columns> <DataGridTemplateColumn Header="Operation" IsReadOnly="True" x:Name="abc" > <DataGridTemplateColumn.CellTemplate> <DataTemplate > <StackPanel Orientation="Horizontal">
<ComboBox x:Name="comList" IsReadOnly="True" IsEditable="True" Tag="{Binding ID}" HorizontalContentAlignment="Center" SelectionChanged="ComboBox_SelectionChanged" DisplayMemberPath="Name" SelectedValuePath="Value" SelectedIndex="{Binding ItemList,Converter={StaticResource ComboxSelIndexConverter},Mode=OneWay}" ItemsSource="{Binding ItemList,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"> </ComboBox> </StackPanel> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> </DataGrid.Columns> </DataGrid>
cs:
ComboxSelIndexConverter.cs
public class ComboxSelIndexConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var abcs = (ObservableCollection<ABC>)value; if (abcs == null) { return -1; } else { if (abcs.Count == 0) { return -1; } var abc = abcs.FirstOrDefault(f => f.Des == "1"); if (abc != null) { return abcs.IndexOf(abc); } return -1; } } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } }
Model数据源模型
public class ABC : INotifyPropertyChanged { public ABC() { } public string id; public string ID { get { return id; } set { id = value; OnPropertyChanged("ID"); } } public string des; public string Des { get { return des; } set { des = value; OnPropertyChanged("Des"); } } public string name; public string Name { get { return name; } set { name = value; OnPropertyChanged("Name"); } } protected internal virtual void OnPropertyChanged(string propertyName) { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } public event PropertyChangedEventHandler PropertyChanged; } public class People : INotifyPropertyChanged { public People() { Genre = new Genre(); ItemList = new ObservableCollection<ABC>(){ new ABC(){ ID = "1",Name = "AAA",des="1"}, new ABC(){ ID = "2",Name = "BBB",des="0"} }; } public string ID { get; set; } public string Name2 { get; set; } public string Name { get; set; } public string Price { get; set; } public ObservableCollection<ABC> itemList; public ObservableCollection<ABC> ItemList { get { return itemList; } set { itemList = value; OnPropertyChanged("ItemList"); } } public Genre Genre; protected internal virtual void OnPropertyChanged(string propertyName) { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } public event PropertyChangedEventHandler PropertyChanged; } public class Genre { public string Name { get; set; } }
数据源绑定
public partial class MainWindow : Window, INotifyPropertyChanged { public MainWindow() { InitializeComponent(); } ObservableCollection<People> m_Peoples = new ObservableCollection<People>(); public event PropertyChangedEventHandler PropertyChanged; protected internal virtual void OnPropertyChanged(string propertyName) { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } public ObservableCollection<People> People { get { return m_Peoples; } set { m_Peoples = value; OnPropertyChanged("People"); } } public static ObservableCollection<People> GetPeopleAll() { ObservableCollection<People> People = new ObservableCollection<People>(); for (int i = 0; i < 4; i++) { People.Add(new People() { ID = (i + 1).ToString(), Name = "李四" + (i + 1).ToString(), Name2 = "测试文本" + (i + 1).ToString(), Genre = new Genre() { Name = "张三" + (i + 1).ToString() }, Price = "100" + (i + 1).ToString() }); } return People; } private void Window_Loaded(object sender, RoutedEventArgs e) { People = GetPeopleAll(); dataGrid.DataContext = People; } }