当DataContext已设置为View Model时,参考查看XAML中的成员

时间:2016-11-12 09:05:48

标签: c# wpf xaml

我想知道为什么我不能在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
        }

    }
}

1 个答案:

答案 0 :(得分:0)

正如评论中所建议的那样......

命名主窗口并在绑定

中使用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);