【问题标题】:ContextMenu as staticresource issuesContextMenu 作为静态资源问题
【发布时间】:2016-02-03 09:51:24
【问题描述】:

我一直在为我遇到的一个问题摸不着头脑,最终将其归结为上下文菜单作为静态资源的问题。

我遇到的问题是,当我将上下文菜单移动到静态资源中,并使用数据触发器根据对象的状态加载上下文菜单时,按钮命令似乎卡在绑定在第一次加载,但其他绑定工作正常。

我有以下,一个包含使用自定义项目模板的列表视图的视图,这个项目模板是:

 <DataTemplate x:Key="appListTemplate">
    <Button cal:Message.Attach="Run" HorizontalAlignment="Stretch" VerticalAlignment="Center">
        <Button.Style>
            <Style TargetType="{x:Type Button}">
                <Setter Property="Background" Value="#BBF7F7F7"/>
                <Setter Property="Cursor" Value="Hand"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type Button}">
                            <Grid Height="50" HorizontalAlignment="Stretch" Background="{TemplateBinding Background}">

                                <Border CornerRadius="5" Height="35" Width="35" Background="SkyBlue" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="10,0,0,0"/>

                                <Label Content="{Binding AppName}" ToolTip="{Binding AppStatus}" VerticalAlignment="Center" Margin="50,0,0,0" FontSize="16"/>

                                <Image Source="{Binding Icon}" ToolTip="{Binding AppIconName}" Stretch="UniformToFill" Height="20" Width="20" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,15,0"/>

                                <StackPanel VerticalAlignment="Top">
                                    <Line Stroke="#FFCDCDCD" Stretch="Fill" X2="1" />
                                    <Line Stroke="#FFEAEAEA" Stretch="Fill" X2="1" />
                                </StackPanel>
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding AppStatus}" Value="{x:Static enum:AppStatus.DISABLED}">
                        <Setter Property="IsEnabled" Value="False"/>
                        <Setter Property="Background" Value="Lime"/>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding AppStatus}" Value="{x:Static enum:AppStatus.NOACCESS}">
                        <Setter Property="Opacity" Value="0.5"/>
                        <Setter Property="ContextMenu" Value="{StaticResource ResourceKey=NoAccessContextMenu}" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding AppStatus}" Value="{x:Static enum:AppStatus.INSTALLED}">
                        <Setter Property="ContextMenu" Value="{StaticResource ResourceKey=InstalledContextMenu}"/>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding AppStatus}" Value="{x:Static enum:AppStatus.NOTINSTALLED}">
                        <Setter Property="ContextMenu" Value="{StaticResource ResourceKey=UninstalledContextMenu}"/>
                    </DataTrigger>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Background" Value="#FFF7F7F7"/>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </Button.Style>
    </Button>
</DataTemplate>

如您所见,根据状态会加载不同的上下文菜单。这些定义为:

 <ContextMenu x:Key="InstalledContextMenu" StaysOpen="False">
    <MenuItem Header="{Binding AppName}" HorizontalContentAlignment="Right" FontWeight="Bold" IsEnabled="False"/>
    <Separator/>
    <MenuItem x:Name="RunApplication" Header="Run" cal:Message.Attach="Run"/>
    <MenuItem Header="Uninstall" cal:Message.Attach="Uninstall"/>
</ContextMenu>
<ContextMenu x:Key="UninstalledContextMenu" StaysOpen="False">
    <MenuItem Header="{Binding AppName}" HorizontalContentAlignment="Right" FontWeight="Bold" IsEnabled="False"/>
    <Separator/>
    <MenuItem x:Name="Install" Header="Install" cal:Message.Attach="Install"/>
</ContextMenu>
<ContextMenu x:Key="NoAccessContextMenu" StaysOpen="False">
    <MenuItem Header="{Binding AppName}" HorizontalContentAlignment="Right" FontWeight="Bold" IsEnabled="False"/>
    <Separator/>
    <MenuItem x:Name="RequestAccess" Header="Request Access" cal:Message.Attach="RequestAccess"/>
</ContextMenu>

当您右键单击列表中的第一项时,问题就出现了,它会正确显示选项 E.G

SHIPPING
--------
Run
Uninstall

这项工作是 100%,但是当您右键单击列表中的第二项时,您会得到以下信息:

PROJECTS
--------
Run
Uninstall

如您所见,appname 绑定更新正常,但是当您单击卸载时,它会调用交付 VM 上的卸载方法,而它应该调用项目 VM 上的卸载。这将继续发生在每个项目调用 Shipping VM 上的方法时。

我完全不知道我能做些什么,甚至不知道为什么会这样。任何帮助都将受到欢迎。

【问题讨论】:

  • 快速解决方法是将Bind 转换为SelectedItemSelectedItem
  • 已经有一个绑定,这个样式在一个单独的样式表中,绑定调用直接调用该列表视图中每个项目的视图模型,如果我直接在数据模板中定义上下文菜单,它工作正常,只是它是一个导致问题的静态资源。
  • @user1412240 你的输出窗口有绑定表达式错误吗?
  • 不,没有错误。绑定工作正常 {Binding AppName} 并指向正确的数据上下文,但是 cal:Message.Attach 只会调用第一个数据上下文的方法,所以如果我打开上下文菜单进行运输,所有其他上下文菜单命令都在说项目点到运输上下文,即使 appname 绑定正确显示项目。

标签: c# wpf xaml caliburn.micro


【解决方案1】:

好的,多亏了人们的一些提示,我终于找到了这个。 这个问题是因为上下文菜单不是可视树中的,微软的“修复”是让上下文菜单继承它的父数据上下文,但是这只发生一次,很明显在更改数据上下文时,例如在更改选定项目时一个列表视图,数据上下文永远不会更新。

为了解决这个问题,我将上下文菜单更改为以下内容。

<ContextMenu x:Key="InstalledContextMenu" DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}" StaysOpen="False">
    <MenuItem Header="{Binding AppName}" HorizontalContentAlignment="Right" FontWeight="Bold" IsEnabled="False"/>
    <Separator/>
    <MenuItem x:Name="RunApplication" Header="Run" cal:Action.TargetWithoutContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource AncestorType=ContextMenu}}" cal:Message.Attach="Run"/>
    <MenuItem Header="Uninstall" cal:Action.TargetWithoutContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource AncestorType=ContextMenu}}" cal:Message.Attach="Uninstall"/>
</ContextMenu>
<ContextMenu x:Key="UninstalledContextMenu" DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}" StaysOpen="False">
    <MenuItem Header="{Binding AppName}" HorizontalContentAlignment="Right" FontWeight="Bold" IsEnabled="False"/>
    <Separator/>
    <MenuItem x:Name="Install" cal:Action.TargetWithoutContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource AncestorType=ContextMenu}}"  Header="Install" cal:Message.Attach="Run"/>
</ContextMenu>
<ContextMenu x:Key="NoAccessContextMenu" DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}" StaysOpen="False">
    <MenuItem Header="{Binding AppName}" HorizontalContentAlignment="Right" FontWeight="Bold" IsEnabled="False"/>
    <Separator/>
    <MenuItem x:Name="RequestAccess" cal:Action.TargetWithoutContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource AncestorType=ContextMenu}}" Header="Request Access" cal:Message.Attach="RequestAccess"/>
</ContextMenu>

如您所见,我现在为数据上下文创建自己的绑定,然后为每个菜单项上的 caliburn 微操作设置目标上下文。必须为每个菜单项执行此操作有点麻烦,但似乎是最简单的解决方法。

【讨论】:

  • 实际上您的DataContext 已正确更新,证明:菜单项中的文本正在更改。这里的问题是Micro 没有选择不同的 DataContext,因此在第一个 DataContext 上调用操作。
  • 我也想过这个问题,但是正如你提到的 menuitem 文本的绑定正在改变,这也是由 caliburn.mirco 处理的
  • &lt;MenuItem Header="{Binding AppName}" 我认为这意味着Binding 引擎对此负责。但是cal 可能正在拦截我不知道的功能。就我个人而言,我从未使用过cal
  • 除非我弄错了,否则由 cal 处理。我可能是错的,我必须承认在这种情况下更有意义:D
猜你喜欢
  • 1970-01-01
  • 2018-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-11
  • 2013-07-27
  • 1970-01-01
  • 2012-11-05
相关资源
最近更新 更多