当DataContext已经设置为视图模型时,在XAML中引用视图成员
本文关键字:视图 XAML 成员 引用 模型 DataContext 设置 | 更新日期: 2023-09-27 18:17:29
我想知道为什么我不能从后面的代码直接引用共享的部分类成员,在xaml绑定中(没有在DataContext上设置部分类的实例)。
从我的阅读中,我理解XAML中的x:Class属性相当于CLR中的部分类声明。这就是为什么可以通过节点的'Name'属性在后面的代码中引用XAML节点。为什么不能从XAML中引用在后面代码中的部分类中实现的对象?
我意识到我可以设置一个DataContext,但我更喜欢在共享的部分类(负责视图内容和行为)中组合视图,并在DataContext上设置视图模型对象,如下所示:
mainWindow.xaml
<Window x:Class="button_binding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid Margin="0,0,183,134">
<Button x:Name="button0" Command="{Binding Button0.DelegateClick}" Content="{Binding Button0.Content}" HorizontalAlignment="Left" Margin="112,82,0,0" VerticalAlignment="Top" Width="75"/>
<Button x:Name="button1" Command="{Binding Button1.DelegateClick}" Content="{Binding Button1.Content}" HorizontalAlignment="Left" Margin="112,134,0,0" VerticalAlignment="Top" Width="75"/>
<ToggleButton Name="button2" IsChecked="{Binding Button2.On, Mode=OneWayToSource}" Content="{Binding Button2.Content}" HorizontalAlignment="Left" Margin="213,134,0,0" VerticalAlignment="Top"/>
<Button Content="MODEL" Command="{Binding VM.TargetButton.Push}" HorizontalAlignment="Left" Margin="273,86,-14,0" VerticalAlignment="Top" Width="75"/>
</Grid>
</Window>
mainWindow.xaml.cs
namespace button_binding
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public ObservableButton Button0 { get; set; }
public ObservableButton Button1 { get; set; }
public ObservableToggleButton Button2 { get; set; }
public ViewModel VM { get; set; }
public MainWindow ()
{
// finish off the view build
// These objects contain pure view state and UI behaviour
// no reference to model or view controls!
Button0 = new ObservableButton(new List<string> { "Paused", "Logging" }, false);
Button1 = new ObservableButton(new List<string> { "Paused", "Logging" }, false);
Button2 = new ObservableToggleButton(new List<string> { "Log All", "Log VBA" }, false);
InitializeComponent();
// build the view model and connect it to the view
VM = new ViewModel(button2);
DataContext = VM; //<-- this is what I want to do
// DataContext = this; //<-- this is what I have to do
}
}
}
如注释所示…
命名主窗口,并在绑定
中使用ElementName<Window x:Class="button_binding.MainWindow"
x:Name="View"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid Margin="0,0,183,134">
<Button x:Name="button0" Command="{Binding ElementName=View, Path=Button0.DelegateClick}" Content="{Binding ElementName=View, Path=Button0.Content}" HorizontalAlignment="Left" Margin="112,82,0,0" VerticalAlignment="Top" Width="75"/>
<Button x:Name="button1" Command="{Binding ElementName=View, Path=Button1.DelegateClick}" Content="{Binding ElementName=View, Path=Button1.Content}" HorizontalAlignment="Left" Margin="112,134,0,0" VerticalAlignment="Top" Width="75"/>
<ToggleButton Name="button2" IsChecked="{Binding ElementName=View, Path=Button2.On, Mode=OneWayToSource}" Content="{Binding ElementName=View, Path=Button2.Content}" HorizontalAlignment="Left" Margin="213,134,0,0" VerticalAlignment="Top"/>
<Button Content="MODEL" Command="{Binding TargetButton.Push}" HorizontalAlignment="Left" Margin="273,86,-14,0" VerticalAlignment="Top" Width="75"/>
</Grid>
</Window>
使用RelativeSource FindAncestor
<Window x:Class="button_binding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid Margin="0,0,183,134">
<Button x:Name="button0" Command="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}}, Path=Button0.DelegateClick}" Content="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}}, Path=Button0.Content}" HorizontalAlignment="Left" Margin="112,82,0,0" VerticalAlignment="Top" Width="75"/>
<Button x:Name="button1" Command="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}}, Path=Button1.DelegateClick}" Content="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}}, Path=Button1.Content}" HorizontalAlignment="Left" Margin="112,134,0,0" VerticalAlignment="Top" Width="75"/>
<ToggleButton Name="button2" IsChecked="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}}, Path=Button2.On, Mode=OneWayToSource}" Content="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}}, Path=Button2.Content}" HorizontalAlignment="Left" Margin="213,134,0,0" VerticalAlignment="Top"/>
<Button Content="MODEL" Command="{Binding TargetButton.Push}" HorizontalAlignment="Left" Margin="273,86,-14,0" VerticalAlignment="Top" Width="75"/>
</Grid>
</Window>
或
<Window x:Class="button_binding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<RelativeSource x:Key="View" Mode="FindAncestor" AncestorType="{x:Type Window}"></RelativeSource>
</Window.Resources>
<Grid Margin="0,0,183,134">
<Button x:Name="button0"
Command="{Binding Button0.DelegateClick, RelativeSource={StaticResource View}}"
Content="{Binding Button0.Content, RelativeSource={StaticResource View}}"
HorizontalAlignment="Left" Margin="112,82,0,0" VerticalAlignment="Top" Width="75"/>
<Button x:Name="button1" Command="{Binding Button1.DelegateClick, RelativeSource={StaticResource View}}"
Content="{Binding Button1.Content, RelativeSource={StaticResource View}}"
HorizontalAlignment="Left" Margin="112,134,0,0" VerticalAlignment="Top" Width="75"/>
<ToggleButton Name="button2" IsChecked="{Binding Button2.On, RelativeSource={StaticResource View}, Mode=OneWayToSource}"
Content="{Binding Button2.Content, RelativeSource={StaticResource View}}"
HorizontalAlignment="Left" Margin="213,134,0,0" VerticalAlignment="Top"/>
<Button Content="MODEL" Command="{Binding TargetButton.Push}" HorizontalAlignment="Left"
Margin="273,86,-14,0" VerticalAlignment="Top" Width="75"/>
</Grid>
</Window>
然后,在后面的代码中,可以删除VM对象并只执行…
// build the view model and connect it to the view
DataContext = new ViewModel(button2);