【问题标题】:Difficulty updating UI when contents of ObservableCollection is changed?更改 ObservableCollection 的内容时难以更新 UI?
【发布时间】:2015-08-26 14:49:15
【问题描述】:

我有一个绑定到 observablecollection 的组合框:

 <ComboBox 
        HorizontalAlignment="Left" Margin="586,51,0,0" VerticalAlignment="Top" Width="372" 
        SelectedItem="{Binding PrimaryInsurance.SelectedInsurance}"
        ItemsSource="{Binding PrimaryInsurance.AllPatientInsurance}" 
        ItemTemplate="{StaticResource InsuranceTemplate}" />

observablecollection 本身定义为:

 private ObservableCollection<Insurance> _allPatientInsurance;
 public ObservableCollection<Insurance> AllPatientInsurance
    {
        get { return _allPatientInsurance; }
        set { if (_allPatientInsurance == value) return; _allPatientInsurance = value; OnPropertyChanged("AllPatientInsurance"); }
    }

现在 Insurance 封装从数据库下载的数据并添加 INotifyPropertyChanged 为:

 public string CompanyName
    {
        get { return insurance_View.Companyname; }
        set { if (insurance_View.Companyname == value) return; insurance_View.Companyname = value; OnPropertyChanged("CompanyName"); }
    }

其中 insurance_View 是从数据库下载的原始数据记录。

一切都好。

但是,在“撤消”操作中,我想将已编辑的 insurance_View 记录替换为其原始记录,例如:

 internal void UnDo()
    {
        insurance_View = (Insurance_View)pre_edit_Insurance_View.Clone();
    }

虽然 insurance_View 的编辑版本已正确更改回其原始形式,但显示并未更新。此外,在 ObservableCollection 中用原始版本的保险替换编辑后的保险版本,如:

  AllPatientInsurance.Remove(Old Insurance);
  AllPatientInsurance.Add(New Insurance);

销毁所有绑定并显示空白记录。

那么,当保险的内容发生变化而不破坏保险对象时,更新显示的最佳方法是什么?有没有更好的办法?

编辑#1。为了清楚起见,我试图替换保险对象中的数据记录,它是绑定到显示器的保险对象。我不想替换正在显示的整个集合。唯一想到的是将编辑记录的每个值替换为其原始值,但这似乎很乏味,所以我希望有更好的方法。

编辑#2。有什么方法可以在封装时触发保险设置器 Insurance_View 记录是否已更改?

编辑#3。保险模板:

        <!--DataTemplate for the Combobox Insurance List-->
    <DataTemplate x:Key="InsuranceTemplate">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="20" />
                <ColumnDefinition Width="120" />
                <ColumnDefinition Width="50" />
                <ColumnDefinition Width="14" />
                <ColumnDefinition Width="50" />
                <ColumnDefinition Width="60" />
            </Grid.ColumnDefinitions>
            <TextBlock Text="{Binding XNotInEffect}"  Grid.Column="0" />
            <TextBlock Text="{Binding CompanyName}" Grid.Column="1"/>
            <TextBlock Text="{Binding EffectiveDateFrom}" Grid.Column="2"/>
            <TextBlock Text="--" Grid.Column="3" />
            <TextBlock Text="{Binding EffectiveDateTo}" Grid.Column="4" />
            <TextBlock Text="{Binding InsuranceType}" Grid.Column="5"/>
        </Grid>
    </DataTemplate>

另外,请注意,简单地删除然后添加相同的保险对象会导致其从组合框下拉列表中消失。示例:

    AllPatientInsurance.Remove(SelectedInsurance);
    AllPatientInsurance.Add(SelectedInsurance);

TIA

【问题讨论】:

  • 保险对象是否隐含 INotifyPropertyChanged?

标签: c# wpf xaml data-binding


【解决方案1】:

我想您的 InsuranceTemplate 已绑定到保险的属性,例如 CompanyName,因此侦听来自 Insurance 实例(模板的 DataContext)的属性更改事件。因此,由于撤消操作不会通过调用相应的设置器(而是通过更改 insurance_view)来更改属性,因此您必须在撤消操作后手动触发每个更改的属性的属性更改事件(OnPropertyChanged("CompanyName") 等)以通知视图。

【讨论】:

  • 是的...看起来是这样。我希望有一个更好的方法,或者至少是一个 for 循环,它可以替换不同对象上匹配属性的值。 :(
  • 您在ObservableCollection 中删除和添加实例的替代方法也应该有效。您的意思是“销毁所有绑定”所选项目吗?因为如果您删除当前选定的项目,则 SelectedItem 将设置为 null。添加新保险后(应该是带有未完成值的旧保险),您必须在后面的代码中选择它。
  • 当我使用 ComboBox 上的下拉菜单时,应该显示“新”保险对象的位置有一个空白行。所有其他保险对象都可以正常显示。
  • 请把你的保险模板贴出来好吗?
  • 删除和添加应该更新视图,至少没有数据库后端我没有问题。我想这是一个时间问题。您是否在数据库更新完成后执行删除/添加?如果您不在 UI 线程中执行 Remove/Add(例如在数据库更新回调之后),您可以尝试将 Remove/Add 包装在 UI 调度程序中。
【解决方案2】:

在其自己的可观察集合中跟踪旧保险。在您的撤消中,您可以将旧集合分配给 AllPatientInsurance,并让资产承担繁重的工作。

//initialize this elsewhere as appropriate
private ObservableCollection<Insurance> _oldPatientInsurance;

internal void UnDo()
{
    insurance_View = (Insurance_View)pre_edit_Insurance_View.Clone();
    AllPatientInsurance = _oldPatientInsurance;
}

【讨论】:

  • Insurance_View 包含在 Insurance 对象中。内部 UnDo() 不知道它所在的集合。此外,我试图不替换现有的 AllPatientInsurance 集合..只是集合公开的对象中的一条记录。谢谢。
【解决方案3】:

此代码不起作用,因为 SelectedInsurance 在从集合中删除时变为空:

 AllPatientInsurance.Remove(SelectedInsurance);
 AllPatientInsurance.Add(SelectedInsurance);

但是,如果保留了对 SelectedInsurance 的引用,则可以将其添加回来:

 SelectedInsurance.Reset();
 var x = SelectedInsurance;
 AllPatientInsurance.Remove(SelectedInsurance);
 AllPatientInsurance.Add(x);
 SelectedInsurance = x;

Reset() 在哪里

 internal void Reset()
    {
        insurance_View = (Insurance_View)pre_edit_Insurance_View.Clone();
    }

最后一行将组合框设置回最初选择的项目。

如此简单。 :)

【讨论】:

    猜你喜欢
    • 2014-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-28
    • 2018-05-18
    • 1970-01-01
    • 2023-03-08
    • 2013-09-14
    相关资源
    最近更新 更多