Pergunta

Eu notei isso algumas vezes ao usar menus com comandos, eles não são muito dinâmicos, confira isso. Estou criando um menu a partir de uma coleção de cores, eu o uso para colorir uma coluna em um datagrid. De qualquer forma, quando eu trago o menu (é um menu de contexto), a ligação do parâmetro de comando acontece e vincula à coluna em que o menu de contexto foi aberto. No entanto, da próxima vez que eu o trago, parece que o WPF armazena em cache o menu e ele não rebeu o parâmetro de comando. Para que eu possa definir a cor apenas na coluna inicial em que o menu de contexto apareceu.

Eu tenho essa situação no passado, tornando o menu totalmente dinâmico e destruindo a coleção quando o menu fechou e forçando uma reconstrução na próxima vez que ele se abrir, eu não gosto desse hack. Alguém tem uma maneira melhor?

    <MenuItem
       Header="Colour"
       ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:ResultEditorGrid}}, Path=ColumnColourCollection}"
       ItemTemplate="{StaticResource colourHeader}" >
       <MenuItem.Icon>
          <Image
             Source="{StaticResource ColumnShowIcon16}" />
       </MenuItem.Icon>
       <MenuItem.ItemContainerStyle>
          <Style
             TargetType="MenuItem"
             BasedOn="{StaticResource systemMenuItemStyle}">
             <!--Warning dont change the order of the following two setters
                                otherwise the command parameter gets set after the command fires,
                                not mush use eh?-->
             <Setter
                Property="CommandParameter">
                <Setter.Value>
                   <MultiBinding>
                      <MultiBinding.Converter>
                         <local:ColumnAndColourMultiConverter/>
                      </MultiBinding.Converter>
                      <Binding RelativeSource="{RelativeSource AncestorType={x:Type DataGridColumnHeader}}" Path="Column"/>
                      <Binding Path="."/>
                   </MultiBinding>
                </Setter.Value>
             </Setter>
             <Setter
                Property="Command"
                Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:ResultEditorGrid}}, Path=ColourColumnCommand}" />
          </Style>
       </MenuItem.ItemContainerStyle>
    </MenuItem>
Foi útil?

Solução

O problema é que os generosos do contexto são aparentemente a raiz de sua própria árvore visual Eu li em algum lugar que leva o datacontext a seus pais, mas apenas uma vez no carregamento; portanto, se o Datacontext dos pais altera, os menitems não. (Infelizmente, não consigo encontrar um link para esse direito, não)

Eu já encontrei esse problema antes, e o que fiz foi usar Padrão de ramificação virtual de Josh Smith. É bastante técnico, mas o artigo me ajudou a entender muito bem o que estava acontecendo com essa bobagem visual.

Essencialmente, você cria essa ponte que se liga ao datacontext da exibição. A ponte é criada Como um recurso estático, permitindo que você se vincule a ele no menu de contexto, mesmo que esteja fora da árvore visual.

Adicione isso ao seu xaml:

<Window.Resources>
   <!-- This is the "root node" in the virtual branch
   attached to the logical tree. It has its
   DataContext set by the Binding applied to the
   Window's DataContext property. -->
   <FrameworkElement x:Key="DataContextBridge" />
</Window.Resources>

<Window.DataContext>
   <!-- This Binding sets the DataContext on the "root node"
   of the virtual logical tree branch.  This Binding
   must be applied to the DataContext of the element
   which is actually assigned the data context value. -->
   <Binding
    Mode="OneWayToSource"
    Path="DataContext"
    Source="{StaticResource DataContextBridge}"
   />
</Window.DataContext>

Esta é a ponte de que falei. Ele pega o DataContext e __pushes It_ para o datacontext Bridges, que é (como eu disse antes) um recurso estático.

Então você simplesmente isso no contextmenu DataContext:

 DataContext="{Binding
               Source={StaticResource DataContextBridge},
               Path=DataContext}"

Agora jogue fora todo o caminho relativo etc. e use encadernação regular dentro dos itens do menu, e você deve ficar bem. O DataContext atualizará como de costume.

Apenas uma nota:

Obviamente, você terá que ter alguma propriedade no DataContext para discernir qual comando usar, mas tenho certeza de que você pode descobrir. Esta solução apenas lida com a maneira como o contextmenu não atualiza

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top