【问题标题】:How do I pass a property of Datatemplate's Datatype to Caliburn.Micros Message.Attach?如何将 Datatemplate 的 Datatype 的属性传递给 Caliburn.Micros Message.Attach?
【发布时间】:2019-10-12 13:01:09
【问题描述】:

我目前正在为一个小组项目实施菜单导航系统。我们正在使用 Caliburn.Micro 和 MVVM 模式。

该菜单位于ShellView.xaml 中,并且基于使用 Role 属性过滤的List<NavigationMenuItem>

public class NavigationMenuItem
    {
        public IScreen ViewModel { get; set; }
        public string IconPath { get; set; }

        public string Role { get; set; }

        public NavigationMenuItem(IScreen viewModel, string iconPath, string role)
        {
            ViewModel = viewModel;
            IconPath = iconPath;
            Role = role;
        }
    }

菜单显示得很好,但现在我想将 ViewModel 属性传递给 ShellViewModel.cs 中的一个方法,这样我就可以激活视图更改。这是ShellView.xaml 到目前为止的样子:

<Window
    x:Class="P3GG.Views.ShellView"
    xmlns:cal="http://www.caliburnproject.org"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:P3GG.Views"
    xmlns:models="clr-namespace:P3GG.Models"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:templates="clr-namespace:P3GG.Templates"
     xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
    Title="Title"
    Width="800"
    Height="600"
    WindowStartupLocation="CenterScreen"
    mc:Ignorable="d">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <ListBox Visibility="{Binding SidebarIsVisible, Converter={StaticResource BooleanToVisibilityConverter}, FallbackValue=Collapsed}"
                 Grid.Column="0"
                 Background="#333333"
                 x:Name="NavigationMenu">
            <ListBox.ItemTemplate>
                <DataTemplate DataType="models:NavigationMenuItem">
                    <Button cal:Message.Attach="Handle( <!-- pass content of NavigationMenuItem.ViewModel --> )" Style="{StaticResource BtnSidebar}">
                        <Image Margin="20" Source="{Binding IconPath}"/>
                    </Button>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <ContentControl  Grid.Column="1" x:Name="ActiveItem"/>
    </Grid>
</Window>

ShellViewModel.cs 目前包含两个 Handle 方法:

public void Handle(Screen screen)
public void Handle(User user)

如何将给定 NavigationMenu 的 ViewModel 属性传递给 Handle(Screen) 方法?

编辑 为每个请求添加了处理方法

public void Handle(Screen screen)
        {
            if (screen is LoginViewModel)
            {
                SidebarIsVisible = false;
                NotifyOfPropertyChange(() => SidebarIsVisible);
            }
            else
            {
                SidebarIsVisible = true;
                NotifyOfPropertyChange(() => SidebarIsVisible);
            }
            ActivateItem(screen);
        }

【问题讨论】:

  • 你的意思是“我如何通过”而不是解析
  • 我当然知道。谢谢指正!
  • 嗯,Handle 是给 EventAgregator 的,能不能展示一下你的 shellview/shellviewmodel 代码?
  • 我在 OP 中添加了完整的方法。我只是使用聚合器来传递屏幕。

标签: c# wpf xaml data-binding caliburn.micro


【解决方案1】:

也许你可以尝试这样的事情,正如here 解释的那样:

<Button cal:Message.Attach="[Event Click] = [Action Handle($dataContext)]" Style="{StaticResource BtnSidebar}">
    <Image Margin="20" Source="{Binding IconPath}"/>
</Button>

这会将完整视图模型 (DataContext) 传递给您的处理程序。

要传递视图模型的特定属性,请使用here 所示的长语法:

<Button Style="{StaticResource BtnSidebar}">
    <i:Interaction.Triggers> 
        <i:EventTrigger EventName="Click"> 
            <cal:ActionMessage MethodName="Handle"> 
               <cal:Parameter Value="{Binding ViewModel}" /> 
            </cal:ActionMessage> 
        </i:EventTrigger> 
    </i:Interaction.Triggers> 
    <Image Margin="20" Source="{Binding IconPath}"/>
</Button>

i 定义为

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

您还可以将ButtonDataContext 属性更改为感兴趣的属性,例如:

<Button DataContext="{Binding ViewModel}" cal:Message.Attach="[Event Click] = [Action Handle($dataContext)]" Style="{StaticResource BtnSidebar}">
    <Image Margin="20" Source="{Binding IconPath}"/>
</Button>

所以只有正确的属性会传递给你的亨德勒,但这感觉就像一个黑客。 点击时,这会将ButtonDataContext 作为Handle 方法的参数,它应该是NavigationMenuItem

【讨论】:

  • 可行,但我想传递项目的特定属性。
  • 好吧,我到了某个地方,但是 actionMessage 发送的对象似乎不是“屏幕”类型。我可以通过创建一个 Handle(object value) 来接收它,然后重铸它。关于如何正确获取数据类型的任何想法?
  • 你能显示你的NavigationMenuItem类的代码吗?也许您的ViewModel 属性不是Screen 类型?您收到的实际类型是什么?没有更多信息,很难提供帮助。
猜你喜欢
  • 1970-01-01
  • 2012-04-17
  • 2021-01-08
  • 2016-02-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多