WPF: пункты меню только прикрепляют параметры команды один раз
-
26-09-2019 - |
Вопрос
Я заметил пару раз, когда используете меню с командами, они не очень динамичны, проверьте это. Я создаю меню из коллекции цветов, я использую его для цвета колонны в DataGrid. В любом случае, когда я впервые поднимаю меню (его контекстное меню), привязка параметра команд происходит, и он связывается с столбцом, на котором был открыт контекстное меню. Однако в следующий раз я приведу его, кажется, что 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>
Решение
Проблема в том, что контекстмен Видимо корень их собственного визуального дерева Я читал где-то, что требуется NataContext его родитель, но только один раз на загрузку, поэтому, если родители DataContext меняют меню. (К сожалению, я не могу найти ссылку для этого права не)
Я столкнулся с этой проблемой раньше, а что я сделал, было использовать Виртуальный филиал Джоша Смита. Отказ Это довольно техническое, но статья помогла мне действительно хорошо понять, что происходит с этим визуальным деревом ерунды.
По сути, вы создаете этот мост, который связывается с DataContext представления. Мост создан как статический ресурс, позволяя вам связывать с ним из контекстного меню, даже если он находится за пределами визуального дерева.
Добавьте это на свой 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>
Это мост, о котором я говорил. Требуется DataContext и __Pushes IT_ к мостам DataContext, который (как я уже сказал) статический ресурс.
Тогда вы просто это к DataContext ContextMenu:
DataContext="{Binding
Source={StaticResource DataContextBridge},
Path=DataContext}"
Теперь выбросьте весь относительный путь и т. Д. и использовать регулярное связывание внутри пунктов меню, и вы должны быть в порядке. DataContext будет обновляться как обычно.
Только одна заметка:
Вы, очевидно, должны иметь некоторое свойство в DataContext, чтобы различить, какую команду использовать, но я уверен, что вы можете понять это. Это решение просто имеет дело с возможностью обновления ContextMenu