【问题标题】:WPF MVVM Observable Collection doesn't update GUI correctlyWPF MVVM Observable Collection 无法正确更新 GUI
【发布时间】:2018-06-15 07:55:01
【问题描述】:

我正在尝试创建一个应用程序,您可以在其中选择一道菜并自动添加到您的订单中。

因此,我使用 ListView 创建了这个 XAML 代码,其中包含您订单中的菜肴。它应该在添加菜肴时自动更新(使用RelayCommand)。

<UserControl.DataContext>
    <viewn:ViewModelOrder/>
</UserControl.DataContext>

<ListView x:Name="CommandListView" ItemsSource="{Binding Order}" >
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name_Dish}"/>
            <GridViewColumn Header="Price" DisplayMemberBinding="{Binding Price_Dish}" />
        </GridView>
    </ListView.View>
</ListView>

您可以在下面看到订单ObservableCollection 绑定到ListView

public class ViewModelOrder : ViewModelBase, INotifyPropertyChanged
{
    private ObservableCollection<Dish> _Order;    
    public ObservableCollection<Dish> Order
    {
        get { return _Order; }
        set
        {
            _Order = value;
            OnPropertyChanged("Order");
        }
    }
}

真正奇怪的是,业务逻辑按预期工作(ObservableCollection 的订单中装满了盘子),但是这些更改并未显示在 ListView 上。

更奇怪的是,当应用程序运行时,我在 Binding 末尾添加了一个点,所以它看起来像这样:ItemsSource="{Binding Order.}",UI 完全按照预期更新(它显示了之前的所有菜肴每当我添加另一个时添加和更新)。所以我不确定是什么导致了这个问题。

你知道可能是什么问题吗?

更新

我的 XAML 中的绑定似乎存在问题。实际上,输出窗口显示以下错误:

System.Windows.Data Error: 40 : BindingExpression path error: 'AddDishToOrder' property not found on 'object' ''Dish_801880DFD6EB7B0C17C1467B62FCB73FB779084FCF737D81239B8934238C3474' (HashCode=45081147)'. BindingExpression:Path=AddDishToOrder; DataItem='Dish_801880DFD6EB7B0C17C1467B62FCB73FB779084FCF737D81239B8934238C3474' (HashCode=45081147); target element is 'Button' (Name=''); target property is 'Command' (type 'ICommand')

在为所有菜品生成的此按钮上抛出此错误:

<ItemsControl Name="DishesItemsControl" ItemsSource="{Binding Dishes}">
<ItemsControl.ItemTemplate>
    <DataTemplate>
        <Button Command="{Binding AddDishToOrder}">
            <Button.DataContext>
                <viewn:ViewModelOrder/>
            </Button.DataContext>
        </Button>
    </DataTemplate>
</ItemsControl.ItemTemplate>

绑定正在调用这个方法:

private RelayCommand _addDishToOrder;
public RelayCommand AddDishToOrder
{
    get
    {
        if (_addDishToOrder == null)
        {
            //The DoAddDish method simply add the dish to the ObservableCollection
            _addDishToOrder = new RelayCommand<object>(DoAddDish);
        }
        return _addDishToOrder;
    }
    set { _addDishToOrder = value; }
}

如果我理解正确,错误来自用于将菜肴添加到订单中的按钮。但是我不能完全理解它们有什么问题,因为我在调试时正确调用了该方法。

【问题讨论】:

  • 您能告诉我们您如何将DataContext 分配给您的Window Control 或您正在使用的任何东西吗?这似乎是Binding 问题,因此我们需要一个完整的可视化树或至少一个可以重现该问题的示例。
  • 不,@Mahmoud。这个ItemsSource Binding 在这里引起了问题。它没有正确解决。顺便说一句@Antoine Delia,您不会在输出窗口中收到任何错误:40?
  • 您能更新您的帖子并粘贴错误详情吗?
  • 请添加一个minimal reproducible example,说你有绑定错误而不显示有问题的绑定是没有用的。
  • 这一切都搞砸了,伙计。您需要向我们提供您正在使用的完整代码。 从不在 DataTemplate 中分配数据上下文。

标签: c# wpf listview mvvm data-binding


【解决方案1】:

尝试像这样在绑定中添加“路径”关键字:

<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Path=Name_Dish}"/>

【讨论】:

  • 那将没有效果。 Path 在没有指定属性时被推断出来。
  • Binding 具有接受 string 路径的 this constructor overload。指定Path 属性时,使用无参数构造函数。两种方法都应该达到相同的结果。
【解决方案2】:

正如@XAMIMAX 指出的那样,我的DataContext 里面有一个Button,这是完全错误的。所以,我把按钮的代码改成了这样,现在它完全可以工作了:

<Button Command="{Binding AddDishToOrder}" DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext}"/>

【讨论】:

  • 您仍在分配 DataContext 内部的 DataTemplate 替换您的代码:Command="{Binding DataContext.AddDishToOrder, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"。
【解决方案3】:

如果我正确理解你的问题,你不应该用属性包装 _Order,你应该简单地使用:

public class ViewModelOrder : ViewModelBase, INotifyPropertyChanged
{   
    public ObservableCollection<Dish> Order{get;set;}
}

【讨论】:

    猜你喜欢
    • 2021-12-25
    • 1970-01-01
    • 2014-10-24
    • 2018-11-09
    • 2015-01-26
    • 2012-10-20
    • 1970-01-01
    • 2014-07-10
    相关资源
    最近更新 更多