简体   繁体   中英

Exposing Multiple Databinding sources

I feel like I'm missing a fairly fundamental concept to WPF when it comes to databinding, but I can't seem to find the right combination of Google keywords to locate what I'm after, so maybe the SO Community can help. :)

I've got a WPF usercontrol that needs to databind to two separate objects in order to display properly. Both objects must be dynamically set from an outside source. Thus far I've simply been using the DataContext property of the form for dynamic object binding, but that only allows for one object to be referenced. I feel like this is a simple problem and that I must be missing something obvious.

My previous attempt looks something like this:

<UserControl.Resources>
    <src:Person x:Key="personSource" />
    <src:Job x:Key="jobSource" />
</UserControl.Resources>
<TextBox Text="{Binding Source={StaticResource personSource}, Path=Name" />
<TextBox Text="{Binding Source={StaticResource jobSource}, Path=Address" />

This will bind to any defaults I give the classes just fine, but If I try to dynamically set the objects in code (as I show below) I don't see any change.

Person personSource = FindResource("personSource") as Person;
personSource = externalPerson;
Job jobSource= FindResource("jobSource") as Job;
jobSource = externalJob;

What am I missing?

I would probably use a CustomControl with two DependencyProperties. Then the external site that uses your custom control could bind the data that they want to that control, also by using a custom control you can template the way the control looks in different situations.

Custom control code would look something like:

public class CustomControl : Control
{
    public static readonly DependencyProperty PersonProperty =
        DependencyProperty.Register("Person", typeof(Person), typeof(CustomControl), new UIPropertyMetadata(null));
    public Person Person
    {
        get { return (Person) GetValue(PersonProperty); }
        set { SetValue(PersonProperty, value); }
    }


    public static readonly DependencyProperty JobProperty =
        DependencyProperty.Register("Job", typeof(Job), typeof(CustomControl), new UIPropertyMetadata(null));
    public Job Job
    {
        get { return (Job) GetValue(JobProperty); }
        set { SetValue(JobProperty, value); }
    }

    static CustomControl()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl), new FrameworkPropertyMetadata(typeof(CustomControl)));
    }
}

Generic.xaml is a file that should be created for you and could have a Style that looks something like this:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication3">


    <Style TargetType="{x:Type local:CustomControl}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:CustomControl}">
                    <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}">
                        <StackPanel>
                            <TextBox Text="{TemplateBinding Person.Name}" />
                            <TextBox Text="{TemplateBinding Job.Address}" />
                        </StackPanel>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

Finally, when you go to use your control you would do something like this.

<src:CustomControl Person="{Binding Person}" Job="{Binding Job}" />

The reason your text boxes don't update is that you are binding them to a StaticResource. As the name implies these resources are static and don't post change notifications. And because Binding is a MarkupExtension and does not derive from DependencyObject you can't use a DynamicResource.

Try creating depedency properties on your control to reference the Person and Job objects.

Then set the DataContext of the UserControl to reference itself.

DataContext="{Binding RelativeSource={RelativeSource Self}}"

Then you can use dot notation to reference the required properties.

<TextBox Text="{Binding Path=Person.Name" />
<TextBox Text="{Binding Path=Job.Address" />

Or use the source parameter

<TextBox Text="{Binding Source=Person, Path=Name" />
<TextBox Text="{Binding Source=Job, Path=Address" />

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