【问题标题】:Exposing ObservableCollection as a DependencyProperty将 ObservableCollection 公开为 DependencyProperty
【发布时间】:2015-01-27 16:53:10
【问题描述】:

我看过其他问题:

ObservableCollection dependency property does not update when item in collection is deleted

MVVM binding to a User Control with an ObservableCollection dependency property

...一个偶数...

https://go4answers.webhost4life.com/Example/databinding-observable-collection-196835.aspx

但他们要么在做我没有做的事情,要么就是我没明白。

  • 我正在使用 MVVM。
  • 我在一个包含成员列表的视图上有一个 DataGrid。
  • 当用户右键单击 DataGrid 时,我会打开一个 RelayCommands 菜单(从 ViewModel 绑定)。
  • 如果用户选择了多个成员,我希望 MergeMember.CanExecute 返回 true。
  • 由于我不能绑定到SelectsItems的集合,我有一个DependencyProperty,即我填写选择变化时。

我的问题是 DependencyProperty 会在属性本身发生更改时触发更改(即 ObservableCollection 被“更新”),而不是在集合中的项目发生更改时触发更改。

我看到的其他解决方案在视图中捕获了变化,我正在尝试将变化通知 ViewModel。

如何将 DependencyProperty 集合的更改通知 ViewModel?

如果您觉得需要,我可以发布代码示例,但我一直在尝试的所有事情都一团糟。

【问题讨论】:

  • 不。 VM 应将 OC 公开为只读属性。如果 VM 需要知道集合是否更改,则它应该订阅 CollectionChanged 事件。如果它需要了解 OC 内物品的变化,它应该在它们被添加/从集合中删除时子/取消它们的 INPC。不是没有魔法。
  • 你是说视图可以直接改变集合?不需要绑定? View 可以知道 VM,但 VM 仍然不需要知道 View...?嗯。我会看看结果如何。谢谢。
  • 我不清楚这里发生了什么,但通常情况下就是这样。不确定您在数据网格上执行的操作无法在 VM 中完成。
  • DataGrid.SelectedItems 集合不是依赖属性,因此我无法将其绑定到 VM。这是一个以可接受的方式将信息从 View 获取到 VM 的简单案例。我被困在绑定上,因为这就是 DataGrid.SelectedItem 对象和其他一些信息从 View 到 VM 的方式。但我想我可以直接从 View 代码隐藏中设置 VM 属性。
  • 如果我在你的位置,我会简单地将 DataGrid 和密切相关的 UI(CRUD 按钮、标签等)包装到用户控件中。通过代码隐藏来破解和削减你的痛苦(这都是 UI 工作,所以很好!相信我。),并将你的方式绑定到幸福。通过 UC 表面的 DP 展示您需要的一切。布拉姆。完毕。继续下一个故事。

标签: c# wpf mvvm datagrid


【解决方案1】:

通常在您描述的情况下,我使用此解决方案。 为了知道您的 DataGrid 中的哪些项目被选中(在 MVVM 应用程序中),您不需要将 ObservableCollection 公开为 DependencyProperty。

在您的 DataGridRow 模型中添加一个属性:

public bool IsSelected
{
    get
    {
        return isSelected;
    }
    set
    {
        if (isSelected != value)
        {
            isSelected = value;
            OnPropertyChanged("IsSelected"); // if you are implementing INotifyPropertyChanged
        }
    }
}

关于 XAML,您可以在 DataGrid 中使用 Style 来绑定 IsSelected 属性:

<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Path=People}">
    <DataGrid.Columns>
        <!-- your columns are here -->
    </DataGrid.Columns>

    <DataGrid.ItemContainerStyle>
        <Style TargetType="DataGridRow">
            <Setter Property="IsSelected" Value="{Binding Path=IsSelected}" />
        </Style>
    </DataGrid.ItemContainerStyle>
</DataGrid>

通过这种方式,在 ViewModel 中,您始终知道哪些项目被选中而无需订阅事件,并且您可以在 MergeMember RelayCommand 的 CanExecute 方法中编写逻辑。

【讨论】:

  • 您说“DataGridRow 模型”在我的情况下是我的成员类,对吧?这就是 DataGrid 的行,Members。我试过这样的东西,但我想我把它和我当时正在尝试的其他东西混在一起了。等我回家再试试,谢谢。如果它有效,我会回来并将其标记为“已回答”。别担心。
  • 是的,我的意思是每个 DataGridRow 的模型对象,在你的例子中是 Member 类。让我知道您的代码是否能够工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多