如有不理解的地方請留言。
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; } }