一、绑定自定义对象

1.绑定

<StackPanel Name="StudentPanel" >
<TextBox Text="{Binding Path=Id}" Height="30" Width="100"></TextBox>
<TextBox Text="{Binding Path=Age}" Height="30" Width="100"></TextBox>
<TextBox Text="{Binding Path=Name}" Height="30" Width="100"></TextBox>
<Button Name="btn1" Click="btn1_Click" Height="30" Width="100"></Button>
</StackPanel>

 

public partial class MainWindow : Window
{
Student student;
public MainWindow()
{
InitializeComponent();
student = new Student(1,15,"Tom");
}

private void btn1_Click(object sender, RoutedEventArgs e)
{
StudentPanel.DataContext = student;
}
}

class Student
{
private int id;
private int age;
private string name;

public Student(int id, int age, string name)
{
this.id = id;
this.age = age;
this.name = name;
}

public int Id { get => id; set => id = value; }
public int Age { get => age; set => age = value; }
public string Name { get => name; set => name = value; }
}

 

2.输入控件自动修改绑定类

当给TextBox输入数据并失去焦点后,Student会自动赋值

注意如果按钮可以用回车来执行,这就使得在未更新的情况下进行了提交

最好按钮前强制转移焦点

<Button Name="btn2" Click="btn2_Click" IsDefault="True"  Height="30" Width="100"></Button>

 

private void btn2_Click(object sender, RoutedEventArgs e)
{
FocusManager.SetFocusedElement(this, (Button)sender);
MessageBox.Show(student.Name);
}

 

3.更改通知

如果有按钮改变student类的name,从而想达到自动更新界面name对应的textbox的效果,有三种方法

(1)把Product中的属性改未依赖项属性

(2)引发 porpertyNameChange事件

(3)student类实现InotifyPropertyChanged接口

 

private void btn2_Click(object sender, RoutedEventArgs e)
{
student.Name = "Lick";
MessageBox.Show(student.Name);
}

 

class Student :INotifyPropertyChanged
{
private int id;
private int age;
private string name;


public Student(int id, int age, string name)
{
this.id = id;
this.age = age;
this.name = name;
}

public int Id { get => id; set => id = value; }
public int Age { get => age; set => age = value; }

//新增
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
PropertyChanged(this, e);
}
public string Name
{
get => name;
set {
name = value;
OnPropertyChanged(new PropertyChangedEventArgs("Name"));
}
}
}

 

二、绑定对象集合

所有派生自ItemsControl的类,都支持集合数据绑定。(ListBox,Combobox,ListView,DataGrid,Menu,TreeView)

ItemsControl类属性

  • ItemsSource
  • DisplayMemberPath
  • ItemTemplate

1.绑定

<StackPanel Name="StudentPanel" DataContext="{Binding ElementName=listBox,Path=SelectedItem}" >
<ListBox Name="listBox" Height="100" Width="200"></ListBox>
<TextBox Text="{Binding Path=Id}" Height="30" Width="100"></TextBox>
<TextBox Text="{Binding Path=Age}" Height="30" Width="100"></TextBox>
<TextBox Text="{Binding Path=Name}" Height="30" Width="100"></TextBox>
</StackPanel>

 

Student student1;
Student student2;
List<Student> list = new List<Student>();
public MainWindow()
{
InitializeComponent();
student1 = new Student(1,15,"Tom");
student2 = new Student(2, 17, "Maiko");
list.Add(student1);
list.Add(student2);
listBox.ItemsSource = list;
}

2.添加删除

使用ObservableCollection<Student> 代替List<Student>,可以实现增删效果

Student student1;
Student student2;
ObservableCollection<Student> list = new ObservableCollection<Student>();
public MainWindow()
{
InitializeComponent();
student1 = new Student(1,15,"Tom");
student2 = new Student(2, 17, "Maiko");
list.Add(student1);
list.Add(student2);
listBox.ItemsSource = list;
}

private void btn1_Click(object sender, RoutedEventArgs e)
{
list.Remove((Student)listBox.SelectedItem);
}

 

3.绑定Ado.net

绑定和增删

DataTable dt = new DataTable();
public MainWindow()
{
InitializeComponent();

dt.Columns.Add("Id", typeof(int));
dt.Columns.Add("Age", typeof(int));
dt.Columns.Add("Name");

DataRow dr1 = dt.NewRow();
dr1["Id"] = 1;
dr1["Age"] = 15;
dr1["Name"] = "Tom";
dt.Rows.Add(dr1);
DataRow dr2 = dt.NewRow();
dr2["Id"] = 2;
dr2["Age"] = 19;
dr2["Name"] = "Luck";
dt.Rows.Add(dr2);

listBox.ItemsSource = dt.DefaultView;
}

private void btn1_Click(object sender, RoutedEventArgs e)
{
((DataRowView)listBox.SelectedItem).Row.Delete();
}

 

4.绑定到Linq表达式

 

 

三、提高大列表性能 ??

1.虚拟化

ListBox ListView DataGrid 自动使用VirtualizingStackPanel面板布局它们的子元素。

 

ComboBox需要明确通过ItemPanelTemplate来支持虚拟化

<ComboBox>
<ComboBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel></VirtualizingStackPanel>
</ItemsPanelTemplate>
</ComboBox.ItemsPanel>
</ComboBox>

 

TreeView默认支持虚拟化是关闭着的,开启

<TreeView VirtualizingStackPanel.IsVirtualizing="True"></TreeView>

 

有可能会破坏虚拟化的条件:

  • ScrollViewer中放置列表控件
  • 改变列表控件的模板并且没有使用ItemsPresenter
  • 不使用数据绑定

 

2.项容器再循环

<ListBox VirtualizingStackPanel.VirtualizationMode="Recycling"></ListBox>

 

3.缓存长度

<ListBox VirtualizingStackPanel.CacheLength="100" VirtualizingStackPanel.CacheLengthUnit="Item"></ListBox>

 

4.延迟滚动

 

<ListBox ScrollViewer.IsDeferredScrollingEnabled="True"></ListBox>

 

<ListBox VirtualizingStackPanel.ScrollUnit="Pixel"></ListBox>

 

四、验证 ???

 

1.在数据对象中进行验证

public partial class MainWindow : Window
{
Student student;
public MainWindow()
{
InitializeComponent();
student = new Student();
//绑定
StudentPanel.DataContext = student;
}

private void btn1_Click(object sender, RoutedEventArgs e)
{
try
{
student.Age =Convert.ToInt32(tb1.Text);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return;
}
MessageBox.Show(student.Age.ToString());
}
}

class Student
{
int age=10;

public int Age {
get => age;
set {
if (value <= 0)
{
throw new Exception("请输入正数");
}
}
}
}

 

2.在绑定级别的验证

ExceptionValidationRule 是预先构建的验证规则,它向WPF报告所有异常

 

五、数据提供者 ??