gpt4 book ai didi

wpf - 嵌套 View 模型的 MVVM 命令绑定(bind)

转载 作者:行者123 更新时间:2023-12-03 10:18:40 25 4
gpt4 key购买 nike

我正在使用下面类图中的 View 模型来使用 DataGrid 进行时间表演示。

顶级类 (ActivityCollectionViewModel) 是网格的 DataContext;它持有的事件集合(ActivityViewModel)是网格中的行项目。该事件有一个分配集合 (AllocationViewModel),它们是行项目 DataGrid 单元格(列)的大部分。

请注意,AllocationVm(单元格)有它自己的命令 MakeFullDayCommand。在当前的设计中,我在 AllocationVm 的父级和祖父级都有等效的命令。我这样做是因为我认为我可以绑定(bind)祖 parent 的命令,然后使用 collectionViewSource 的能力来维护选定的子虚拟机,以便始终调用正确的单元格命令。

在实践中,跟踪是令人困惑的,而且我很难单独绑定(bind)以保持所有内容同步,因此我在 DataGrid 中使用了一些代码,如下所示。

所以我想我会退后一步,看看是否有人可以提出比我所拥有的更简单更有效的设计,或者确认这是一个可行的解决方案并帮助我制定更好的数据绑定(bind)策略。

干杯,
绿柱石

这个怎么运作

下面上下文菜单中的底部命令是我所指的嵌套命令。

enter image description here

代码背后

这段代码丑陋且难以测试!

    /// <summary>
/// Synchronize the <see cref="ActivityViewModel.SelectedAllocationVm"/> here so the input binding
/// key (F8) is always working on the correct command.
/// </summary>
private void OnCurrentCellChanged(object sender, EventArgs e)
{
if (sender == null) return;
var grid = (DataGrid)sender;
if (grid.CurrentColumn == null) return;
var selectedActivity = (ActivityViewModel)grid.CurrentItem;

if (_isEditableDayOfTheWeekColumn(grid.CurrentColumn))
{
var dowCol = (DayOfTheWeekColumn)grid.CurrentColumn;
var index = Convert.ToInt32(dowCol.DowIndex);
selectedActivity.SetSelectedAllocationVm(index);
}
else
{
selectedActivity.SetSelectedAllocationVm(-1);
}
}

/// <summary>
/// Invoke the MakeFullDayCommand when the user double clicks an editable cell;
/// synchronize the selected allocation view model first.
/// </summary>
private void OnDoubleClick(object sender, MouseButtonEventArgs e)
{
if (sender == null) return;
var grid = (DataGrid)sender;
if (grid.CurrentColumn == null) return;

if (!_isEditableDayOfTheWeekColumn(grid.CurrentColumn)) return;

var selectedActivity = (ActivityViewModel) grid.CurrentItem;
var dowCol = (DayOfTheWeekColumn)grid.CurrentColumn;
var index = Convert.ToInt32(dowCol.DowIndex);
var allocationVm = selectedActivity.SetSelectedAllocationVm(index);
if (allocationVm.MakeFullDayCommand.CanExecute(null))
{
allocationVm.MakeFullDayCommand.Execute(null);
}
}

/// <summary>
/// Manipululate the context menu to show the correct description of the MakeFullDayCommand.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="System.Windows.Controls.ContextMenuEventArgs"/> instance containing the event data.</param>
void OnContextMenuOpening(object sender, ContextMenuEventArgs e) {
if (sender == null) return;
var grid = (DataGrid)sender;
if (grid.CurrentColumn == null) return;

const int INDEX_OF_MAKE_FULL_DAY_CMD = 1;
if (_isEditableDayOfTheWeekColumn(grid.CurrentColumn)) {
var selectedActivity = (ActivityViewModel) grid.CurrentItem;
var dowCol = (DayOfTheWeekColumn) grid.CurrentColumn;
var index = Convert.ToInt32(dowCol.DowIndex);
var allocationVm = selectedActivity.SetSelectedAllocationVm(index);
var menuItem = allocationVm.MakeFullDayCommand.ToMenuItem();

if (grid.ContextMenu.Items.Count == 1) {
Log.Info("{0}", allocationVm.MakeFullDayCommand.HeaderText);
grid.ContextMenu.Items.Add(menuItem);
}
else {
var currentItem = (MenuItem) grid.ContextMenu.Items.GetItemAt(INDEX_OF_MAKE_FULL_DAY_CMD);
if (currentItem.Command != menuItem.Command) {
// remove the outdated menu item before adding back the new one
grid.ContextMenu.Items.Remove(currentItem);
grid.ContextMenu.Items.Add(menuItem);
}
}
}
else
{
if (grid.ContextMenu.Items.Count == 2)
{
// we aren't on an editable cell - remove the command altogether
grid.ContextMenu.Items.RemoveAt(INDEX_OF_MAKE_FULL_DAY_CMD);
}
}
}

enter image description here

最佳答案

根据我对数据网格(以及看起来像你的)的经验,我很难通过嵌套 View 模型将其绑定(bind)到列。上次我尝试使用它时,我最终下载了数据网格的源并重写了一堆以支持我需要的绑定(bind)方式。如果我可以重新开始,我会用我有限的功能从头开始编写自己的。

除此之外,查看向最终用户显示数据的不同方式可能会有所帮助,这种方式在用户体验、编码和可测试性方面可能会更好一些。似乎用户很难查看网格并认为“我应该右键单击该列以度过一整天”。

此外,WPF 的部分优点是能够非常轻松地进行控件。也许这对你来说可能是一条更好的路线?

关于wpf - 嵌套 View 模型的 MVVM 命令绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5540735/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com