gpt4 book ai didi

wpf - 在 MVVM 中使用命令

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

我一直在使用来自 ApuntasNotas 的非常好的示例代码了解有关如何有效使用 MVVM Light Toolkit 的更多信息.

在代码中,在一个例子中,作者似乎利用后面的代码来设置 DataContext 以处理点击事件,我觉得这很困惑。

在 XAML 中,EditNote_Click ContextMenu 中 MenuItem 的事件处理程序 cm在代码隐藏中处理:

    <Window x:Class="ApuntaNotas.MainWindow" Icon="Icons/app_48.ico"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Apunta Notas"
Height="480"
x:Name="Ventana"
Width="640"
Background="Beige"
DataContext="{Binding Main, Source={StaticResource Locator}}">
.
.
.
<ScrollViewer VerticalScrollBarVisibility="Auto">
<ItemsControl Background="Beige" Padding="15" Tag="Hello" x:Name="IC"
ItemsSource="{Binding Notes}">
<ItemsControl.LayoutTransform>
<ScaleTransform ScaleX="{Binding Value, ElementName=zoomSlider}" ScaleY="{Binding Value, ElementName=zoomSlider}" />
</ItemsControl.LayoutTransform>
<ItemsControl.ContextMenu>
<ContextMenu Name="icCM">
<MenuItem Header="{Binding Source={StaticResource LocStrings}, Path=DeleteAllNotes}" Command="{Binding DeleteAllNotesCommand}" />
</ContextMenu>
</ItemsControl.ContextMenu>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.ContextMenu>
<ContextMenu Name="cm">
<MenuItem Header="{Binding Source={StaticResource LocStrings}, Path=Edit}" Click="EditNote_Click"/>
<MenuItem Header="{Binding Source={StaticResource LocStrings}, Path=Delete}" Click="DeleteNote_Click" />
<Separator />
<ComboBox Loaded="CmbNoteCategory_Loaded" SelectionChanged="CmbNoteCategory_SelectionChanged">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</ContextMenu>
.
.
.

在代码隐藏中, EditNote_Click处理程序定义如下:
private void EditNote_Click(object sender, RoutedEventArgs e)
{
var menuItem = e.Source as MenuItem;
if (menuItem != null)
ViewModel.EditNoteCommand.Execute(menuItem.DataContext as Model.Note);
}
EditNoteCommand具有以下签名:
public RelayCommand<Note> EditNoteCommand { get; private set; }

我的问题是,作者为什么不链接 EditNoteCommand命令 - 已经写入并可用 - 到 Command MenuItem 的属性在 XAML 中?

例如,我尝试替换以下内容,它已编译,但产生了异常(如下所示)。我怀疑我的方法是合理的,但是我错过了将 DataContext 或其他东西传递给命令代码的一些东西。我将 DataContext 绑定(bind)重置为 Main为方便命令绑定(bind):
<MenuItem Header="{Binding Source={StaticResource LocStrings}, Path=Edit}" DataContext="{Binding Main, Source={StaticResource Locator}}" Command="{Binding EditNoteCommand}"/>

此尝试生成以下引用 other 的异常。在 EditNote 内- EditNoteCommand 调用的方法:

编辑注:
private void EditNote(Note other)
{
ActualNote = other;
SelectedCategory = other.Category;
}

异常(exception):
System.NullReferenceException was unhandled   Message=Object reference not set to an instance of an object.   Source=ApuntaNotas   StackTrace:
at ApuntaNotas.ViewModel.MainViewModel.EditNote(Note other) in C:\Documents and Settings\wcatlan\My Documents\Visual Studio 2010\Projects\ApuntaNotas\trunk\ApuntaNotas\ViewModel\MainViewModel.cs:line 171
at GalaSoft.MvvmLight.Command.RelayCommand`1.Execute(Object parameter)
at MS.Internal.Commands.CommandHelpers.CriticalExecuteCommandSource(ICommandSource commandSource, Boolean userInitiated)
at System.Windows.Controls.MenuItem.InvokeClickAfterRender(Object arg)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.DispatcherOperation.InvokeImpl()
at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
at System.Threading.ExecutionContext.runTryCode(Object userData)
at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Windows.Threading.DispatcherOperation.Invoke()
at System.Windows.Threading.Dispatcher.ProcessQueue()
at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
at System.Windows.Threading.Dispatcher.Run()
at System.Windows.Application.RunDispatcher(Object ignore)
at System.Windows.Application.RunInternal(Window window)
at System.Windows.Application.Run(Window window)
at System.Windows.Application.Run()
at ApuntaNotas.App.Main() in C:\Documents and Settings\wcatlan\My Documents\Visual Studio 2010\Projects\ApuntaNotas\trunk\ApuntaNotas\obj\Debug\App.g.cs:line 0
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart() InnerException:

最佳答案

你绝对是在正确的轨道上,除非需要,否则不想使用代码隐藏 - 所以在你的 MVVM 中继续遵循该原则,你会做得很好。

我想您会发现这里的作者正在使用代码隐藏来解决使命令参数正确的问题。
对于编辑注释命令 - 正在编辑的注释的 View 模型是必需的参数。这就是他们在后面的代码中所做的 -

menuItem.DataContext as Model.Note

您遇到的问题是关于在同一命令中访问被单击的菜单项和“主” View 模型。

如果您要移动 EditNoteCommand进入 NotesViewModel (或任何类 Notes )你可以将你的命令保存在 XAML 中,如下所示:
<MenuItem Header="{Binding Source={StaticResource LocStrings}, Path=Edit}" Command="{Binding EditNoteCommand}" />

高温下,
斯科特

关于wpf - 在 MVVM 中使用命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5089495/

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