一、绑定自定义对象
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报告所有异常
五、数据提供者 ??