WPF数据绑定时间问题

3

我的绑定出现了问题,但我找不到原因。

我有一个状态类型控件(UserControl),其中包含一个ItemsControl,其绑定依赖于ViewModelBase对象,该对象提供了BrokenRules列表,如下所示:

<ItemsControl ItemsSource="{Binding BrokenRules}" >
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <TextBlock>
                <Hyperlink Foreground="Red" >
                    <TextBlock Text="{Binding Description}" />
                </Hyperlink>
            </TextBlock>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

绑定方式符合我的要求,因为所有违反规则的说明都会显示出来。规则基本上就是一个描述和一个在规则被告知验证自身时执行的委托。
大多数规则在被要求验证自身之前就已经知道了其描述。例如,“名称未赋值”是如果验证委托!Name.IsNullOrEmptyAfterTrim()失败,出现问题的良好描述。
问题出现在特定的规则中,该规则检查重复名称。如果重复检查失败,我想能够说出重复的值,这是事先不可能知道的。因此,当执行验证委托时,规则需要更新描述。
当我进行单元测试或在验证委托中留下调试跟踪时,损坏的规则说明会更新。但是当我运行应用程序时,损坏的规则说明仍然是之前的样子。
因此,我猜测我的绑定不正确。有人能建议问题/解决方案吗?
问候,Berryl
更新====================
这是我的ViewModelBase类中的代码:
private readonly List<RuleBase> _rules = new List<RuleBase>();

// inheritors add rules as part of construction
protected void _AddRule(RuleBase rule) { _rules.Add(rule); }

public ObservableCollection<RuleBase> BrokenRules { get { return _brokenRules; } }
protected ObservableCollection<RuleBase> _brokenRules;

public virtual IEnumerable<RuleBase> GetBrokenRules()         {
        return GetBrokenRules(string.Empty);
}

public virtual IEnumerable<RuleBase> GetBrokenRules(string property)        {
    property = property.CleanString();

     _brokenRules = new ObservableCollection<RuleBase>();
    foreach (var r in _rules)            {
        // Ensure we only validate this rule 
        if (r.PropertyName != property && property != string.Empty) continue;

        var isRuleBroken = !r.ValidateRule(this);

        if (isRuleBroken) _brokenRules.Add(r);

        return _brokenRules;
    }

你的ViewModelBase类是否实现了INotifyPropertyChanged接口?也就是说,UI界面是否知道Description属性何时发生了变化? - Matt Hamilton
你是否正在向BrokenRules集合中添加项目?它是ObservableCollection吗? - Anero
@Matt。是的,VmBase实现了INPC。至于你回答的第二部分,我认为Aero说得很接近了,如果我不每次重新创建集合实例,那么UI将与更改保持同步。需要仔细研究一下。干杯 - Berryl
RuleBase也实现了INPC吗?如果Description属性的更改应该告知UI,那么它需要实现。 - Jens
@Jens。RuleBase以前没有实现INPC,但现在已经实现了。我将PC事件注册到一个空委托中,以便触发它,这也确实做到了,但UI仍然显示修改之前的描述。 - Berryl
1个回答

1

你必须确保BrokenRules可观察集合实例不会改变,你的视图模型代码应该类似于:

public ObservableCollection<BrokenRule> BrokenRules
{
  get;
  set;
}

private void ValidateRules()
{
  // Validation code
  if (!rule.IsValid)
  {
    this.BrokenRules.Add(new BrokenRule { Description = "Duplicated name found" });
  }
}

如果你做的是这样的事情:

例如:

this.BrokenRules = this.ValidateRules();

你将更改绑定到 ItemsControl 的集合,而没有通知它,这些更改不会反映在用户界面上。


我认为你已经接近了解决方法。我的破损规则列表不是一个ObservableCollection,并且在每个循环中都会创建一个新实例。我已经修复了集合类型,因为这很简单,接下来我将研究如何使用同一集合实例完成此操作。但是,您需要删除变得未破损的规则以及添加破损的规则,这并不是那么容易。干杯! - Berryl
1
@Berryl:不需要创建新的集合,你可以使用.Clear()方法。这样做不会破坏数据绑定。 - Jens
所有这里的评论的结合使得它正确地工作。由于Anero是我唯一可以标记为答案的人,所以我将他的标记为答案。谢谢大家! - Berryl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接