WPF: пункты меню связывают параметры команды только один раз - PullRequest
3 голосов
/ 10 июня 2010

Я заметил это пару раз при использовании меню с командами, они не очень динамичны, проверьте это. Я создаю меню из коллекции цветов, я использую его для раскраски столбца в сетке данных. В любом случае, когда я впервые вызываю меню (это контекстное меню), происходит привязка параметров команды, и она связывается со столбцом, в котором было открыто контекстное меню. Однако в следующий раз, когда я поднимаю его, кажется, что wpf кэширует меню и не перепривязывает параметр команды. поэтому я могу установить цвет только в исходном столбце, в котором появилось контекстное меню.

Я обходил эту ситуацию в прошлом, делая меню полностью динамичным и уничтожая коллекцию, когда меню закрывалось, и заставляя пересобирать при следующем открытии, мне не нравится этот хак. кто-нибудь есть лучший способ?

    <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>

1 Ответ

1 голос
/ 19 марта 2012

Проблема в том, что ContextMenu , по-видимому, является корнем их собственного визуального дерева Я где-то читал, что он принимает текст данных своим родителем, но только один раз при загрузке, поэтому, если родительский текст данных изменяет элементы меню, , (к сожалению, я не могу найти ссылку на это право не)

Я сталкивался с этой проблемой раньше, и я использовал Шаблон виртуальной ветви Джоша Смита . Это довольно технически, но статья помогла мне очень хорошо понять, что происходит с этой ерундой визуального дерева.

По сути, вы создаете этот мост, который привязывается к текстовому тексту представления. Мост создается как статический ресурс , что позволяет привязывать его из контекстного меню, даже если он находится за пределами визуального дерева.

Добавьте это к своему 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>

Это тот мост, о котором я говорил. Он берет текстовый текст данных и __pushes его_ к текстовому мосту данных, который является (как я уже говорил) статическим ресурсом.

Тогда вы просто обращаетесь к текстовому контексту:

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

Теперь отбросьте все относительные пути и т. Д. И используйте регулярное связывание внутри пунктов меню, и все будет в порядке. Текст данных будет обновляться как обычно.

Только одна нота:

Вам, очевидно, нужно будет иметь какое-то свойство в тексте данных, чтобы различать, какую команду использовать, но я уверен, что вы сможете это выяснить. Это решение касается только способа, которым contextmenu не обновляет

...