Возможно ли связать свойство code-behind без установки DataContext?
Как указано,
Я видел пары аналогичного вопроса this или this в формате SO, но я не вижу решения для него.
Я знаю, если мне нужно привязываться к коду, мне нужно установить Datacontext = this
Но моя проблема заключается в том, что мой datacontext уже привязан к моей ViewModel, но я хочу сделать некоторые манипуляции с пользовательским интерфейсом с помощью команды, которая определена в коде.
Возможно ли связать его в xaml? Если да, то как?
EDIT: я пробовал следующее:
<Window x:Class="WpfApplication3.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300" x:Name="_Root">
<Grid x:Name="hellogrid">
<TextBlock x:Name="myTextBlock" Text="AAAA"/>
<Button Margin="82,119,121,120" Name="button2" Content="{Binding Path=Text, ElementName=myTextBlock}"/>
<Button Margin="82,72,121,0" Name="button3" Content="{Binding Path=MyText, ElementName=_Root}" Height="23" VerticalAlignment="Top" />
</Grid>
И код:
public partial class Window1 : Window
{
public string MyText { get; set; }
public Window1()
{
InitializeComponent();
MyText = "ABC";
}
}
Я мог видеть, что Button2 показывает AAAA
, но Button3 ничего не показывает....
Ответы
Ответ 1
ИЗМЕНИТЬ
Лучшее решение IMO - это опубликовано by @Saad Imran в этом SO question...
С помощью этого решения все, что вам нужно сделать, это назвать ваше окно, и привязка к свойству в вашем XAML будет такой же простой, как этот {Binding ElementName=MyWindowName, Path=MyText}
Итак, что вы делаете с Content="{Binding Path=MyText, ElementName=_Root}"
в точности, и свойство Button Content привязано к свойству MyText, но единственное, что вам не хватает, это уведомление об изменении (для этого нужно реализовать интерфейс INotifyPropertyChanged
), поэтому, когда вы установите для свойства MyText значение ABC MyText = "ABC";
уведомление об изменении не отправлено...
Простой способ проверить это, установив свойство MyText явно как таковое:
private string myText = "ABC";
public string MyText
{
get { return myText; }
set { myText = value; }
}
или установка его в конструкторе до InitializeComponent()
:
MyText = "ABC";
InitializeComponent();
Если вы это сделаете, вы заметите, что ваша кнопка будет иметь ABC в качестве ее содержимого, но изменения в свойстве MyText не повлияют на содержимое кнопки, потому что уведомление об изменении отсутствует...
Ответ 2
Конечно,
Существует много типов привязок. Самый простой привязывает свойство к DataContext
, которое обычно унаследовано от родительского объекта
<DataTemplate DataType="{x:Type MyModel}">
<!-- DataContext is object of type MyModel -->
<local:MyView />
</DataTemplate>
или
<Window x:Name="MyWindow">
<!-- DataContext Inherited from Window -->
<TextBlock Text="{Binding SomeProperty}" />
</Window>
где
var SomeObject = new SomeModel();
SomeObject.SomeProperty = "Test";
myWindow.DataContext = SomeObject;
Другие типы привязок включают ElementName
, где вы можете указать целевой элемент пользовательского интерфейса для использования в качестве источника данных для привязки
<StackPanel>
<CheckBox x:Name="SomeCheckBox" />
<TextBlock Text="{Binding ElementName=SomeCheckBox, Path=IsChecked}" />
</StackPanel>
или
<local:MyUserControl x:Name="SomeUserControl">
<Button Command="{Binding ElementName=SomeUserControl, Path=DataContext.SaveCommand}" />
</local:MyUserControl >
Или RelativeSource
, который позволяет вам найти объект относительно текущего объекта для использования в качестве источника данных
<Window Title="Test">
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}}, Path=Title}" />
</Window>
или
<local:MyUserControl>
<Button Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:MyUserControl}}, Path=DataContext.SaveCommand}" />
</local:MyUserControl >
И TemplateBinding
, который связывает это ярлык привязки RelativeSource
, которая привязывается к шаблонизированному объекту
<Button Content="Test">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<TextBlock Text="{TemplateBinding Content}" />
</ControlTemplate>
</Button.Template>
</Button>
Ответ 3
Конечно, вы можете использовать ElementName
:
<Window Name="root"
Class="..."
...>
...
<TextBox Text="{Binding Path=Foo, ElementName=root}" />
Вы также можете сделать это с помощью RelativeSource
, но синтаксис более уродливый...