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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2366945/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-07 01:48:15  来源:igfitidea点击:

WPF Bind to class member in code behind

c#wpfcode-behinddata-binding

提问by jaws

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 中将数据绑定到代码隐藏中的类成员的属性。

<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?

我现在所拥有的不起作用,我做错了什么?

采纳答案by John Bowen

Path needs a Source to go against (Source, DataContext, RelativeSource, ElementName). ElementName can only be used to refer to elements declared in XAML by their x:Name. Try this instead to point to your Window as the source:

Path 需要一个 Source 来对抗(Source、DataContext、RelativeSource、ElementName)。ElementName 只能用于引用在 XAML 中通过 x:Name 声明的元素。试试这个,指向你的 Window 作为源:

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

回答by JaredPar

Data Binding won't work against private fields. It's meant for public properties instead. Try exposing the value _recordpublically 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

回答by Robert Rossney

What I'm seeing here is that your window's class name is Main, that you've added a RecordPropproperty to it, and that you're now trying to bind to the IsCheckedproperty of the element named RecordProp. I think you're a little confused about how names work.

我在这里看到的是,您的窗口的类名是Main,您已经RecordProp向其添加了一个属性,并且您现在正在尝试绑定到IsChecked名为 的元素的属性RecordProp。我认为您对名称的工作方式有些困惑。

Adding the x:Nameattribute to a XAML element creates a field in the window class with that name. 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.

x:Name属性添加到 XAML 元素会在窗口类中创建一个具有该名称的字段。这允许您在代码中引用命名元素,并且它可能让您认为绑定可以做同样的事情。

But that's not how binding finds named elements. The x:Nameattribute alsotakes the object that the XAML element creates and registers it under that name in the window's namescope. (See MSDN's article on XAML namescopes.) That's what binding looks at to resolve element names. Since you're not ever adding the object to the namescope, setting the ElementNameproperty on a binding won't find it.

但这不是绑定查找命名元素的方式。该x:Name属性采用 XAML 元素创建的对象,并在窗口的名称范围中以该名称注册它。(请参阅MSDN 关于 XAML 名称范围的文章。)这就是绑定用于解析元素名称的内容。由于您从未将对象添加到名称范围,因此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 RecordPropproperty (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 RecordPropproperty, the bindings to it will refresh - which is something that won't happen if you just make RecordPropa property (unless you implement change notification).

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

回答by JoeCool

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”,但它没有,我猜是因为它们都引用了完全相同的对象。

This is the solution I used when I ran into the same problem, and I found it to be very intuitive to use.

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