简体   繁体   English

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

[英]WPF Bind to class member in code behind

Pretty simple question, but can't seem to find a complete answer on here... 很简单的问题,但似乎无法在这里找到完整的答案......

I need to databind in xaml to a property of a class member in codebehind. 我需要在xaml中将数据绑定到codebehind中的类成员的属性。

<Window x:Class="Main">
    <customcontrol Name="View" IsChecked="{Binding ElementName=RecordProp, Path=IsViewChecked}" />
...

Where the code behind looks like: 背后的代码如下所示:

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


class Record
{
  public bool IsViewChecked
  {
    get; set;
  }
}

What I've got now doesn't work, what am I doing wrong? 我现在得到的东西不起作用,我做错了什么?

What I'm seeing here is that your window's class name is Main , that you've added a RecordProp property to it, and that you're now trying to bind to the IsChecked property of the element named RecordProp . 我在这里看到的是你的窗口的类名是Main ,你已经为它添加了一个RecordProp属性,并且你现在正试图绑定到名为RecordProp的元素的IsChecked属性。 I think you're a little confused about how names work. 我觉得你对名字的运作方式有点困惑。

Adding the x:Name attribute to a XAML element creates a field in the window class with that name. x:Name属性添加到XAML元素会在窗口类中使用该名称创建一个字段。 This allows you to reference named elements in your code, and it probably has led you to think that binding can do the same thing. 这允许您在代码中引用命名元素,这可能会让您认为绑定可以执行相同的操作。

But that's not how binding finds named elements. 但这不是绑定如何找到命名元素。 The x:Name attribute also takes the object that the XAML element creates and registers it under that name in the window's namescope. x:Name属性获取XAML元素创建的对象,并在窗口的namescope中以该名称注册它。 (See MSDN's article on XAML namescopes. ) That's what binding looks at to resolve element names. (参见MSDN关于XAML名称范围的文章。 )这就是解析元素名称的绑定。 Since you're not ever adding the object to the namescope, setting the ElementName property on a binding won't find it. 由于您没有将对象添加到namescope中,因此在绑定上设置ElementName属性将无法找到它。

There are a couple of things you could conceivably do. 你可以想象有几件事情可以做。 If you really want to bind to a property of the window, you can give the window a name and bind to the property using a property path: 如果您确实要绑定到窗口的属性,可以为窗口指定名称并使用属性路径绑定到该属性:

<Window x:Name="MainWindow" x:Class="Main">
...
   <customcontrol Name="View" IsChecked="
                 {Binding ElementName=MainWindow, 
                  Path=RecordProp.IsViewChecked}" />

Even simpler is to just set the data context in the constructor: 更简单的方法是在构造函数中设置数据上下文:

DataContext = this;

Once you do that, you can just bind to the RecordProp property (and any other property of the window) like this: 一旦你这样做,你可以绑定到RecordProp属性(以及窗口的任何其他属性),如下所示:

<customControl Name="View" IsChecked={Binding RecordProp.IsChecked}/>

Of course, that won't work if you need the window's data context to be set to something else. 当然,如果您需要将窗口的数据上下文设置为其他内容,那么这将不起作用。

Another possibility is to implement the property like this: 另一种可能性是实现这样的属性:

public Record RecordProp 
{
  get { return (Record)Resources["RecordProp"]; }
  set { Resources["RecordProp"] = value; }
}

You can bind to this using (for instance) Binding {DynamicResource RecordProp}, Path=IsChecked" . Since it's a dynamic resource, if something external to the window sets the window's RecordProp property, the bindings to it will refresh - which is something that won't happen if you just make RecordProp a property (unless you implement change notification). 您可以使用(例如) Binding {DynamicResource RecordProp}, Path=IsChecked"绑定到此。由于它是一个动态资源,如果窗口外部的东西设置窗口的RecordProp属性,它的绑定将刷新 - 这是一个如果你只是让RecordProp成为一个属性(除非你实现更改通知),就不会发生这种情况。

Path needs a Source to go against (Source, DataContext, RelativeSource, ElementName). Path需要一个Source来反对(Source,DataContext,RelativeSource,ElementName)。 ElementName can only be used to refer to elements declared in XAML by their x:Name. ElementName只能用于通过x:Name引用在XAML中声明的元素。 Try this instead to point to your Window as the source: 请尝试将此指向您的Window作为源:

IsChecked="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=RecordProp.IsViewChecked}"

I believe I have a simpler answer than the ones stated so far. 我相信我的回答比到目前为止所说的要简单。 Simply add this to the window declaration (the very first tag) in XAML: 只需将其添加到XAML中的窗口声明(第一个标记):

x:Name="this"

Then you can databind like this: 然后你可以像这样数据绑定:

<customcontrol Name="View" IsChecked="{Binding ElementName=this, Path=RecordProp.IsViewChecked}" />

I checked to see if C# complains that there already is a "this," and it didn't, I guess because they both refer to the exact same object. 我检查了C#是否抱怨已经存在“这个”,但它没有,我猜是因为它们都指的是完全相同的对象。

This is the solution I used when I ran into the same problem, and I found it to be very intuitive to use. 这是我遇到同样问题时使用的解决方案,我发现使用起来非常直观。

Data Binding won't work against private fields. 数据绑定不适用于私有字段。 It's meant for public properties instead. 它的意思是公共财产。 Try exposing the value _record publically and bind to that instead. 尝试公开显示值_record并将其绑定到该值。

Reference - http://msdn.microsoft.com/en-us/library/ms743643.aspx 参考 - http://msdn.microsoft.com/en-us/library/ms743643.aspx

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM