WPF绑定到代码后面的类成员

jaw*_*aws 30 c# data-binding wpf code-behind

很简单的问题,但似乎无法在这里找到完整的答案......

我需要在xaml中将数据绑定到codebehind中的类成员的属性.

<Window x:Class="Main">
    <customcontrol Name="View" IsChecked="{Binding ElementName=RecordProp, Path=IsViewChecked}" />
...
Run Code Online (Sandbox Code Playgroud)

背后的代码如下所示:

class Main 
{    
    ...
    private Record _record;
    public Record RecordProp
    {
      get { return _record; }
    }
    ...
}


class Record
{
  public bool IsViewChecked
  {
    get; set;
  }
}
Run Code Online (Sandbox Code Playgroud)

我现在得到的东西不起作用,我做错了什么?

Rob*_*ney 30

我在这里看到的是你的窗口的类名是Main,你已经RecordProp为它添加了一个属性,并且你现在正试图绑定到IsChecked名为的元素的属性RecordProp.我觉得你对名字的运作方式有点困惑.

x:Name属性添加到XAML元素会在窗口类中使用该名称创建一个字段.这允许您在代码中引用命名元素,这可能会让您认为绑定可以执行相同的操作.

但这不是绑定如何找到命名元素.该x:Name属性获取XAML元素创建的对象,并在窗口的名称范围内以该名称注册它.(参见MSDN关于XAML名称范围的文章.)这就是解析元素名称的绑定.由于您没有将对象添加到namescope中,因此ElementName在绑定上设置属性将无法找到它.

你可以想象有几件事情可以做.如果您确实要绑定到窗口的属性,可以为窗口指定名称并使用属性路径绑定到该属性:

<Window x:Name="MainWindow" x:Class="Main">
...
   <customcontrol Name="View" IsChecked="
                 {Binding ElementName=MainWindow, 
                  Path=RecordProp.IsViewChecked}" />
Run Code Online (Sandbox Code Playgroud)

更简单的方法是在构造函数中设置数据上下文:

DataContext = this;
Run Code Online (Sandbox Code Playgroud)

一旦你这样做,你可以绑定到RecordProp属性(以及窗口的任何其他属性),如下所示:

<customControl Name="View" IsChecked={Binding RecordProp.IsChecked}/>
Run Code Online (Sandbox Code Playgroud)

当然,如果您需要将窗口的数据上下文设置为其他内容,那么这将不起作用.

另一种可能性是实现这样的属性:

public Record RecordProp 
{
  get { return (Record)Resources["RecordProp"]; }
  set { Resources["RecordProp"] = value; }
}
Run Code Online (Sandbox Code Playgroud)

您可以使用(例如)绑定到此Binding {DynamicResource RecordProp}, Path=IsChecked".由于它是一个动态资源,如果窗口外部的东西设置窗口的RecordProp属性,它的绑定将刷新 - 如果你只是创建RecordProp一个属性(除非你实现更改通知),这是不会发生的.

  • 您可以简单地将其添加到`Windows`的XAML:`DataContext ="{Binding RelativeSource = {RelativeSource Self}},而不是从代码中设置`Windows`的`DataContext`. (2认同)

Joh*_*wen 27

Path需要一个Source来反对(Source,DataContext,RelativeSource,ElementName).ElementName只能用于通过x:Name引用在XAML中声明的元素.请尝试将此指向您的Window作为源:

IsChecked="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=RecordProp.IsViewChecked}"
Run Code Online (Sandbox Code Playgroud)


Joe*_*ool 7

我相信我的回答比到目前为止所说的要简单.只需将其添加到XAML中的窗口声明(第一个标记):

x:Name="this"
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样数据绑定:

<customcontrol Name="View" IsChecked="{Binding ElementName=this, Path=RecordProp.IsViewChecked}" />
Run Code Online (Sandbox Code Playgroud)

我检查了C#是否抱怨已经存在"这个",但它没有,我猜是因为它们都指的是完全相同的对象.

这是我遇到同样问题时使用的解决方案,我发现使用起来非常直观.