Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

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

like image 221
jaws Avatar asked Mar 02 '10 21:03

jaws


People also ask

What is code behind in WPF?

Code-behind is a term used to describe the code that is joined with markup-defined objects, when a XAML page is markup-compiled. This topic describes requirements for code-behind as well as an alternative inline code mechanism for code in XAML.

What is the use of INotifyPropertyChanged in C#?

The INotifyPropertyChanged interface is used to notify clients, typically binding clients, that a property value has changed.

What is binding path in WPF?

Binding path syntax. Use the Path property to specify the source value you want to bind to: In the simplest case, the Path property value is the name of the property of the source object to use for the binding, such as Path=PropertyName . Subproperties of a property can be specified by a similar syntax as in C#.

How do you bind in XAML?

One-Way Data Binding The following XAML code creates four text blocks with some properties. Text properties of two text blocks are set to “Name” and “Title” statically, while the other two text blocks Text properties are bound to “Name” and “Title” which are class variables of Employee class which is shown below.


2 Answers

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. 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. 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. (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 ElementName property on a binding won't find it.

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:

<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).

like image 102
Robert Rossney Avatar answered Sep 20 '22 18:09

Robert Rossney


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:

IsChecked="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=RecordProp.IsViewChecked}"
like image 28
John Bowen Avatar answered Sep 20 '22 18:09

John Bowen