UWP Community Toolkit 的 MasterDetailsView 中的项目未正确更新

Items not updating properly in UWP Community Toolkit's MasterDetailsView

我正在尝试使用 UWP 社区工具包 MasterDetailsView 来提供编辑界面。但是,当我进行更改时,我似乎无法让列表视图中的各个项目更新它们的属性。

这是我用来连接控件的 XAML 的一部分:

        <controls:MasterDetailsView x:Name="masterDetailsView" Foreground="Black"
                                ItemsSource="{x:Bind libraryVM.Recipes, Mode=TwoWay}"
                                SelectedItem="{x:Bind libraryVM.SelectedRecipe, Mode=TwoWay}"
                                NoSelectionContent="Select an item to view">
        <controls:MasterDetailsView.ItemTemplate>
            <DataTemplate x:DataType="recipes:RecipeVM">
                <StackPanel Margin="0,8">
                    <TextBlock Style="{ThemeResource SubtitleTextBlockStyle}"
                               Text="{x:Bind Name}" />
                </StackPanel>
            </DataTemplate>
        </controls:MasterDetailsView.ItemTemplate>
...

库虚拟机

public class LibraryVM : INotifyPropertyChanged
{
    Library library;
    ObservableCollection<RecipeVM> _Recipes;
    public event PropertyChangedEventHandler PropertyChanged;

    public LibraryVM()
    {
        library = new Library();
        _Recipes = new ObservableCollection<RecipeVM>();
        foreach (var rec in library.Recipes)
        {
            var recipe = _Recipes.FirstOrDefault(r => r.Id == rec.Id);

            if (recipe == null)
            {
                var r = new RecipeVM(rec);
                _Recipes.Add(r);
            }
            else
            {
                recipe.Name = rec.Name;
                recipe.Description = rec.Description;
            }
        }
    }

    public ObservableCollection<RecipeVM> Recipes
    {
        get { return _Recipes; }
        set
        {
            _Recipes = value;
            OnPropertyChanged();
        }
    }

    RecipeVM _SelectedRecipe;


    public RecipeVM SelectedRecipe
    {
        get
        {
            return _SelectedRecipe;
        }

        set
        {
            _SelectedRecipe = value;
            OnPropertyChanged();
        }
    }

    public void SaveChanges()
    {
        if (_SelectedRecipe.Id == Guid.Empty)
        {
            library.CreateNew(_SelectedRecipe.Recipe);
        }
        else
        {
            library.SaveChanges(_SelectedRecipe.Recipe);
        }
    }

    void OnPropertyChanged([CallerMemberName]string propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

}

RecipeVM

public class RecipeVM : INotifyPropertyChanged
{
    Recipe _recipe;
    Recipe _backup;
    public event PropertyChangedEventHandler PropertyChanged;

    public Recipe Recipe
    {
        get
        {
            return _recipe;
        }
    }

    public RecipeVM(Recipe recipe = null)
    {
        _recipe = recipe;

        if(_recipe == null)
        {
            _recipe = new Recipe();
            _recipe.Name = "New Recipe";
        }

        this.IsEditing = false;
    }

    public Guid Id
    {
        get
        {
            return _recipe.Id;
        }

        set
        {
            _recipe.Id = value;
            OnPropertyChanged();
        }
    }

    bool _IsEditing;


    public bool IsEditing
    {
        get
        {
            return _IsEditing;
        }

        set
        {
            _IsEditing = value;
            OnPropertyChanged();
        }
    }

    public string Name
    {
        get
        {
            return _recipe.Name;
        }

        set
        {
            _recipe.Name = value;
            OnPropertyChanged();
        }
    }

    public string Description
    {
        get
        {
            return _recipe.Description;
        }

        set
        {
            _recipe.Description = value;
            OnPropertyChanged();
        }
    }

    public void MakeBackup()
    {
        _backup = new Recipe()
        {
            Id = _recipe.Id,
            Name = _recipe.Name,
            Description = _recipe.Description
        };
    }

    public void RestoreBackup()
    {
        Name = _backup.Name;
        Description = _backup.Description;
    }

    void OnPropertyChanged([CallerMemberName]string propertyName = "")
    {
        if(PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

但是,当我更新任何 RecipeVM 项目时,我似乎无法在 MasterDetailsView 的 ListView 中获取相应的项目进行更新。我相信我已经在适当的地方实施了 INotifyPropertyChanged,但我显然遗漏了一些东西。

更新 我已经验证绑定在其他任何地方都有效。如果我在进行更改后单步执行代码,RecipeVM 和基础 Recipe 会相应更新。

将您的 Textblock 绑定更改为 Text="{Binding Name}"

感谢 Chirag Shah,他为我指明了大致正确的方向。

{x:Bind Name} 更改为 {Binding Name} 有效,但不是因为 x:Bind 有任何问题,而是我对它的理解。

我缺少的是 x:Bind 默认为更加保守的绑定模式。

关于 mode 属性,the documentation 说:

Specifies the binding mode, as one of these strings: "OneTime", "OneWay", or "TwoWay". The default is "OneTime". Note that this differs from the default for {Binding}, which is "OneWay" in most cases.

更新我的 XAML 以明确声明模式解决了问题。

<TextBlock Style="{ThemeResource SubtitleTextBlockStyle}"
    Text="{x:Bind Name, Mode=OneWay}" />

另一个很好的参考是这个问题的答案: