我先描述下我的问题,我使用DataGrid绑定了一个对象集合,有一个编辑操作,通过绑定 selectedItem 将选中对象传递给弹出的编辑界面,我在编辑界面中会通过反射先将传递进来对象的各个属性进行保存,当编辑界面点击取消也就是不更改时将当前对象的值与之前保存起来的值进行一一比较,如果不一样,就用反射进行更改。
这里说下为什么用反射:因为我传递进来的对象是不同的,编辑界面也是使用了propertytools.wpf 这个工具进行的自动生成,所以我并不知道传递进来的对象会是哪个对象。所以用了反射保存原数据最后再用反射进行属性回退。以上功能都实现很好,但是在取消结束编辑界面返回到主界面也就是DataGrid控件后发现通过反射更改的属性值在DataGrid内没有改回来,
举个例子:传递编辑界面了一个 class student{name = 张三},在编辑界面改为 name = 李四,最后点击取消使用反射又将name=张三,此时name 虽然实际值是“张三”,但是在DataGrid显示的却是“李四”。
我在取消返回时也使用了一些方法尝试刷新DataGrid但是都没有用:
RaisePropertyChanged(nameof(TcpSettings));
obj.TcpDg.GetBindingExpression(ItemsControl.ItemsSourceProperty)?.UpdateSource();
以上两种方法我都试过无法刷新
我的反射代码
//存储
foreach
(var propertyInfo
in
comBase.GetType().GetProperties())
{
try
{
object
obj = propertyInfo.GetValue(comBase,
null
);
if
(!obj.GetType().IsArray)
copyProperty.Add(propertyInfo.Name,obj);
}
catch
(Exception e)
{
Console.WriteLine(e);
}
}
//比较赋值
foreach
(var propertyInfo
in
comBase.GetType().GetProperties())
{
try
{
object
value = propertyInfo.GetValue(comBase,
null
);
if
(copyProperty.ContainsKey(propertyInfo.Name))
{
var x = copyProperty[propertyInfo.Name];
if
(!x.Equals(value))
propertyInfo.SetValue(comBase,x,
null
);
}
}
catch
(Exception exception)
{
Console.WriteLine(exception);
}
}
前台绑定代码
<GroupBox Header=
"Tcp通讯"
Visibility=
"{Binding TcpSettings.Count,Converter={StaticResource CountToVisConvertor}}"
>
<DataGrid x:Name=
"TcpDg"
GotFocus=
"TcpDg_OnGotFocus"
ItemsSource=
"{Binding TcpSettings}"
SelectedItem=
"{Binding SelectedItem}"
>
<DataGrid.Columns>
<DataGridTextColumn Header=
"名称"
Binding=
"{Binding Name}"
/>
<DataGridTextColumn Header=
"描述"
Binding=
"{Binding Description}"
/>
<DataGridTextColumn Header=
"解析模块名称"
Binding=
"{Binding AnalyserName}"
/>
<DataGridTextColumn Header=
"Ip地址"
Binding=
"{Binding IP}"
/>
<DataGridTextColumn Header=
"端口"
Binding=
"{Binding Port}"
/>
</DataGrid.Columns>
</DataGrid>
</GroupBox>
对象不同也没有必要用反射, 用json更方便,把json传到编辑界面,编辑了之后通过json再去更新你原来的对象,如果取消了更简单,直接忽略
我尝试过这个方法,但是因为我代码设定的原因这个方法对我有点麻烦,因为界面上三个DataGrid绑定的是三个我内部的子类,三个DataGrid的 selectedItem绑定的是同一个对象也就是DataGrid的ItemSource 的父类这个样子我就不用区分selectedItem 到底 选中的谁了,我直接将selectedItem传递个通用的编辑界面进行编辑就行。如果使用你说的回来再赋值的话我试过不能直接对 selecteditem赋值,对它赋值不会改变集合内部,我就需要查找三个DataGrid的ItemSource集合找到选定的那个对其赋值。现在我 想问问,我的思路遇到的问题没有没有解决方法,如果最后找不到合适的解决方法那就只能我更改下SelectedItem然后按照你说的那种去赋值
按照你给的例子来说 在编辑页更改值是会反应到DataGrid上的 ,张三变成了李四,但是取消的时候 想让不想让张三变成李四 name还是张三,这个时候值没有赋上,所以我觉得你是不是在取消的时候赋值的引用 并不是一开始传进来的引用
其实是赋上值了,你看我在调试模式下截的图,Name 的值是“改之前”。所以使用反射赋值是成功的,但问题是使用反射赋值后并没有通知前台界面去改变界面的绑定数据。我也尝试了两种手动刷新的方式,但是都没有用。
RaisePropertyChanged(nameof(TcpSettings));
//直接调用通知接口
obj.TcpDg.GetBindingExpression(ItemsControl.ItemsSourceProperty)?.UpdateSource();
//obj是前台传入的View对象,调用DataGrid的绑定对象刷新
尝试在Name属性的set里面添加通知试试
这里应该写属性名称而不是类的名称,
如果要对一系列属性进行相应,那么需要写一些列的RaisePropertyChanged,当然也可以用反射取得所有属性,为每个属性调用RaisePropertyChanged
更正一下错别字
RaisePropertyChanged(nameof(TcpSettings));
这里应该写属性名称lrc而不是类的名称,
如果要对一系列属性进行响应,那么需要写一些列的RaisePropertyChanged,当然也可以用反射取得所有属性,为每个属性调用RaisePropertyChanged
感谢两位的回复,通过两位的回复,我查看啦下我的绑定类找到了原因,原因是我的绑定类没有实现INotifyPropertyChanged接口,所以使 用反射赋值后界面并没有改变,至于为什么在编辑页面修改后主页面就改变了,我感觉应该是我使用的propertytools.wpf 类库的原因;我在绑 定类中继承INotifyPropertyChanged接口后发现在反射赋值后主界面也会更改。
但是随之而来的问题就出现啦在编辑页面通过propertytools.wpf 赋值后主界面不会更新啦
我的感觉是InotifyPropertyChanged接口和propertytools.wpf类库之间有冲突~~~~~~
我再去找下propertytools.wpf的资料吧。o(︶︿︶)o 唉