简体   繁体   中英

Binding a WPF control to an Object

I have an object called "Employee", as follows:

class Employee
{
    public string EmpName { get; set; }
    public string Surname { get; set; }

    public Employee(string Name, string Surname) : base()
    {
        this.EmpName = EmpName;
        this.Surname = Surname;
    }

    public Employee()
    {
    }
}

I also have this simple "EmployeeControl" here. Just two labels in a grid:

<UserControl x:Class="LabelBindingTest.EmployeeCtrl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             Name="EmpCtrl"
             d:DesignHeight="120" d:DesignWidth="411">
    <Grid>
        <Label Content="{Binding ElementName=EmpCtrl, Path=EmpName}" Height="28" HorizontalAlignment="Left" Name="label1" VerticalAlignment="Top" Width="81" />
        <Label Content="{Binding ElementName=EmpCtrl, Path=Surname}" Height="28" HorizontalAlignment="Right" Name="label2" VerticalAlignment="Top" Width="81" />
    </Grid>
</UserControl>

(Edit) EmployeeControl codebehind:

   public partial class EmployeeCtrl : UserControl
    {
        Employee thisEmployee = new Employee();

        public string EmpName
        {
            get
            {
                return thisEmployee.EmpName;
            }

            set
            {
                thisEmployee.EmpName = value;
            }
        }

        public string Surname
        {
            get
            {
                return thisEmployee.EmpName;
            }

            set
            {
                thisEmployee.EmpName = value;
            }
        }


        public EmployeeCtrl()
        {
            InitializeComponent();
        }
    }

Now, what I'm trying to do is add "EmployeeControl"s to my window and bind them to Employee objects. Here's my "window" code:

<Window x:Class="LabelBindingTest.MainWindow"
        Name="myWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" xmlns:my="clr-namespace:LabelBindingTest">
    <Grid>
        <my:EmployeeCtrl EmpName="Daniel" Surname="Hammond" HorizontalAlignment="Left" Margin="23,26,0,0" x:Name="employeeCtrl1" VerticalAlignment="Top" Height="97" Width="429" />
    </Grid>
</Window>

I've tried a variety of things but I just can't get it to work. It compiles just fine but the label is empty. I just want to attach my "Employee" object to the "EmployeeCtrl" control. Any ideas on how I go around this? I've read a lot about binding today and I'm still scratching my head. I'm not sure if I need to implement INotifyPropertyChanged as I only set the employee names before runtime for now.

(Edit): I've downloaded Caliburn.Micro and used the same code in the last answer. Same result, empty window.

Here's the whole project. All of it's code should be pasted in this question, though. This is just for convenience sake.

http://www.mediafire.com/?gux3573rz64mupe

Ok, firstly I would strongly recommend considering MVVM as your application gets more complicated, and use an MVVM framework if you're using MVVM . I would recommend Caliburn.Micro which makes view composition like you're doing much much easier. There are other MVVM frameworks available, so evaluate them all.

For your issue, the problem is that your user control doesn't implement its properties as dependency properties. In the XAML, you're setting the EmpName and Surname properties of the user control, but the UI doesn't know that their values have changed after the user control is constructed, and therefore doesn't update itself.

You implement INotifyPropetyChanged on view models when using the MVVM pattern, and dependency properties on user controls. Both of these technqiues will notify the UI of a change and force it to update itself.

So for your user control you can do:

public partial class EmployeeCtrl : UserControl
{
    public static readonly DependencyProperty EmpNameProperty = 
       DependencyProperty.Register("EmpName", typeof(string),
       typeof(EmployeeCtrl), new FrameworkPropertyMetadata(null));

    public static readonly DependencyProperty SurnameProperty = 
       DependencyProperty.Register("Surname", typeof(string),
       typeof(EmployeeCtrl), new FrameworkPropertyMetadata(null));

    public EmployeeCtrl()
    {
        this.InitializeComponent();
    } 

    public string EmpName
    {
       get { return (string)GetValue(EmpNameProperty); }
       set { SetValue(EmpNameProperty, value); }
    }

    public string Surname
    {
       get { return (string)GetValue(SurnameProperty); }
       set { SetValue(SurnameProperty, value); }
    }
}

You don't actually need your Employee class at all at this stage as you aren't using it, but ideally it should implement INotifyPropertyChanged if it's property values will change after construction and you have an instance of it is bound to the UI and you wish the UI to be updated.

you need to implement INotifyPropertyChanged on your EmployeeCtrl's EmpName and Surname property as the Label in this user control needs to be updated about the value change in this property value so that label can update its value. Hence you have to implement Notify change on EmpName and Surname property of the EmployeeCtrl or simply use dependency property for this two property. Hope this helps!!!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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