Родословные привязки от подсказки или контекстно
-
01-10-2019 - |
Вопрос
Что я здесь не так?
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button>
<Button.ToolTip>
<TextBlock Text="{Binding Path=Title, RelativeSource={RelativeSource AncestorType=Window}}" />
Это просто упрощенный пример, который все равно не работает :) На самом деле мне нужно получить значение из другого свойства, которое находится в объеме DataContext окна.
Помоги мне пожалуйста.
Решение
Это сложно, потому что всплывающая подсказка не является частью VisualTree. Здесь Вы видите прохладное решение для той же проблемы с контекстуменными. Так же, как вы можете пойти на подсказку.
ОБНОВИТЬ
К сожалению, ссылка ушла, и я больше не нашел ссылочную статью.
Насколько я помню, ссылочный блог показал, как связываться с DataContext другого Visualtree, который часто является обязательным при привязке от подсказки, контекстмена или всплывающим окном.
Хороший способ сделать это, состоит в том, чтобы обеспечить желаемый экземпляр (например, ViewModel) в свойство Tag-свойство размещения PlactementTarget. В следующем примере это делает это для доступа к командным экземпляре ViewModel:
<Button Tag="{Binding DataContext,RelativeSource={RelativeSource Mode=Self}}">
<Button.ContextMenu>
<ContextMenu>
<MenuItem Command="{Binding PlacementTarget.Tag.DesiredCommand,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ContextMenu}}" .../>
<ContextMenu>
</Button.ContextMenu>
</Button>
Я не проверил это и долгое время я сделал это в последний раз. Пожалуйста, сделайте комментарий, если это не работает для вас.
Обновление 2.
Как оригинальная ссылка, что этот ответ был написан о, ушел, я попал в Archive.org и нашел оригинальную запись в блоге. Отказ Вот это, дословно из блога:
Потому что контекстумен в WPF не существует в визуальном дереве вашей страницы / окна / управления как SE, привязка данных может быть немного сложно. Я искал высоко и низко через Интернет для этого, и наиболее распространенный ответ, кажется, «просто делай это в коде позади». НЕПРАВИЛЬНО! Я не пришел в замечательный мир XAML, чтобы вернуться к тому, чтобы делать вещи в коде.
Вот мой пример, чтобы позволить вам привязать к строке, которая существует как свойство вашего окна.
public partial class Window1 : Window { public Window1() { MyString = "Here is my string"; } public string MyString { get; set; } } <Button Content="Test Button" Tag="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}}"> <Button.ContextMenu> <ContextMenu DataContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}" > <MenuItem Header="{Binding MyString}"/> </ContextMenu> </Button.ContextMenu> </Button>
Важная часть - это тег на кнопке (хотя вы можете так же легко установить DataContext кнопки). Это хранит ссылку на родительское окно. ContextMenu способен доступ к этому через свой свойство размещения размещения. Затем вы можете пройти этот контекст вниз по пунктам меню.
Я признаю, что это не самое элегантное решение в мире. Тем не менее, он бьет настройки в коде позади. Если у кого-то есть еще лучший способ сделать это, я хотел бы услышать это.
Другие советы
За ниже:
PlactementTarget - это элемент управления, который принадлежит контекстному (например, DataGrid). Нет необходимости в собственности «тега».
IseNiabled Персонально со значением «MyProperty» DataGrid «MyProperty».
Я проверил это, и это работает. Имел подобную проблему с обязательным.
<ContextMenu
DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Self}}"
IsEnabled="{Binding myProperty}"
>
Потому что ContextMenu
не в визуальном дереве, связывание не будет работать. Простое решение использует рисунок прокси, вы можете создать класс обертки, который наследует от DependencyObject
и имеет А. DependencyProperty
это будет держать DataContext
вашей Window
, тогда вы можете иметь ресурс прокси в XAML и, наконец, связываете ваш MenuItem
Команда на желаемую команду через прокси-объект.
Образец прокси:
Public class ProxyClass : DependencyObject
{
Public object Data {get; set;}
public static readonly DependencyProperty DataProperty = DependencyProperty.Register("DataProperty", typeof(object), typeof(ProxyClass), new FrameworkPropertyMetadata(null));
}
Как использовать в XAML:
<Window DataContext="{Binding MyViewModel}">
...
<Window.Resources>
<ProxyClass Data={Binding} x:Key="BindingProxy"/>
</Window.Resources>
...
<MenuItem Command="{Binding Source={StaticResource BindingProxy}, Path=Data.MyDesiredCommand"/>
...
</Window>
Что происходит?
Data
свойство ProxyClass
Будет связывать DataContext
из Window
, Тогда у него все ваши коммунты и свойства вашего ViewModel
внутри ProxyClass
ресурс.
Еще одним преимуществом этого подхода является переносимость и повторно использование в нескольких видах и проектах.
Я думаю, что это должно быть сделано так:
{Binding Path=Title, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"