繁体   English   中英

WPF中的绑定属性不会更新

[英]Bound property in WPF doesn't update

我的WPF / MVVM(带有MVVM Light框架)游戏中有一个TextBlock ,它绑定到一个应该反映雇佣工人数量的属性。 我已经确认绑定是完整的,但我无法更新它。

这是我视图中的TextBlock

<TextBlock x:Name="WorkersTextBlock"
           FontFamily="Pericles"
           DataContext="{Binding Guilds[0]}"
           Text="{Binding Workers.Count,
                          StringFormat=Workers : {0},
                          FallbackValue=Workers : 99}" />

我的viewmodel中的属性:

public ObservableCollection<Guild> Guilds
{
    get { return DataManager.Data.Guilds; }
}

同样在我的viewmodel中,更改Worker的Employer属性的命令:

private void ExecuteHireWorkerCommand()
{
    if (SelectedWorker == null)
        return;

    SelectedWorker.Employer = DataManager.Data.Guilds[0];
    Gold -= SelectedWorker.Salary;
    _workerCollectionView.Refresh();
}

在DataManager中,它是一个包含所有数据的单例类:

private ObservableCollection<Guild> _guilds = new ObservableCollection<Guild>();
public ObservableCollection<Guild> Guilds
{
    get { return _guilds; }
}

private ObservableCollection<Worker> _workers = new ObservableCollection<Worker>();
public ObservableCollection<Worker> Workers
{
    get { return _workers; }
}

Guild模型中:

public ObservableCollection<Worker> Workers
{
    get { return DataManager.Data.Workers.Where(w => w.Employer == this).ToObservableCollection(); }
}

Worker的雇主财产是:

public Guild Employer { get; set; }

最后,我的扩展方法(我认为是问题的根源):

public static ObservableCollection<T> ToObservableCollection<T>(this IEnumerable<T> source)
{
    if (source == null)
    {
        throw new ArgumentNullException("source");
    }
    return new ObservableCollection<T>(source);
}

Messageboxes确认通过该命令,正在更新Worker的'Employer属性,但我尝试过的任何内容都不会使TextBlock更新。 我已经尝试在我列出的所有内容上实现RaisePropertyChanged而没有运气。

如果我在初始化数据时将Worker的Employment属性设置为构造函数中的正确的guild,则TextBlock的数字会正确显示,但之后不会更新。 我的预感是Workers属性中的LINQ过滤和扩展方法导致了这个麻烦,但我可能是错的。

如果有人对如何让它发挥作用有任何想法,我很乐意听到它们。 任何有关此事的建议都将不胜感激。 如果您需要更多代码或信息,请询问。

谢谢。

更新:我认为罗恩正走在正确的道路上; 扩展方法可能会打破绑定。 如果是这种情况,任何人都可以给我任何关于如何过滤Guild的Workers属性而不破坏绑定的建议吗? 此外,就setter问题而言,我在Workers属性中添加了一个setter,但它实际上从未触发过。

public ObservableCollection<Worker> Workers
{
    get { return DataManager.Data.Workers.Where(w => w.Employer == this).ToObservableCollection(); }
}

当此属性实际更改时,您不会通知绑定系统。 如果基础集合本身发生了变化,你会没事的。 但是你甚至没有保留对该底层集合的引用 - 你只是返回它。

正常模式会是这样的(假设您在Guild实现了INotifyPropertyChanged

private ObservableCollection<Worker> _Workers;
public ObservableCollection<Worker> Workers
{
    get { return _Workers; }
    set
    {
        if (value != _Workers)
        {
            _Workers = value;
            NotifyPropertyChanged("Workers")
        }
    }
}

但这在某种程度上取决于你如何设置对象。 无论如何,您需要通知系统集合正在以某种方式发生变化。

编辑:你在评论中提到你使用了魔法。 我去看了文档。 它说如何运作

5)显式或隐式应用MagicAttribute转换所有可用的公共属性的setter。

你没有在该属性上设置setter,所以它不会修复它。

我认为你需要重新设计基础数据结构。 但尽管如此,您可以稍微改变它以使其工作。

Workers属性更改为ICollectionView如下所示:

public ICollectionView Workers { get; set; }

然后在Guild模型的contstructor中,您可以从数据管理器填充workers集合,如下所示:

Workers = CollectionViewSource.GetDefaultView(DataManager.Data.Workers);

并向您的ICollectionView添加一个过滤器,如下所示:

Workers.Filter = (worker) => { return (worker.Employer == this); };

每当更新Workers集合时调用Workers.Refresh()

这样你的绑定就不会破坏,你的Workers集合将保留相同的实例。

哦,并将UpdateSourceTrigger=PropertyChanged添加到TextBox绑定中。

就像我说的那样,我会考虑完全重新设计支持数据结构,但不知道为什么或如何实现它我不能说更多。

我还没有测试过你的代码,但是在Guild模型中,返回一个new ObservableCollection (可以在你的扩展方法中看到)可能会破坏你的绑定 ,我建议稍微重新设计一下,以便绑定视图始终与原始视图相关联ObservableCollection实例。

虽然我没有使用你的框架,但是当我实现MVVM模式时,我总是确保我的ViewModel的observable仍然是同一个实例,并且我使用Clear方法来替换我的OnModelChanged方法中的内容,这样你就不会必须处理警告视图这些更改所需的通知,它由ObservableCollection处理。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM