简体   繁体   中英

Binding UserControl DependencyProperty to other UserControl DependencyProperty

I have two UserControls:

public partial class MKSelectMonthUC : UserControl
{
    public static readonly DependencyProperty CurrentYearProperty = DependencyProperty.Register("CurrentYear", typeof(int), typeof(MKSelectMonthUC), new PropertyMetadata(0));
    public int CurrentYear
    {
        get { return (int)GetValue(CurrentYearProperty); }
        set
        {
            SetValue(CurrentYearProperty, value);
        }
    }

    public static readonly DependencyProperty ChatRoomIdProperty = DependencyProperty.Register("ChatRoomId", typeof(int), typeof(MKSelectMonthUC), new PropertyMetadata(0));
    public int ChatRoomId
    {
        get { return (int)GetValue(ChatRoomIdProperty); }
        set
        {
            SetValue(ChatRoomIdProperty, value);
            if(value > 0)
                GetChatReport(ChatRoomId);
        }
    }

}

and

public partial class MKSelectPeriodForChatReportCW : ChildWindow
{
    public static readonly DependencyProperty ChatRoomIdProperty = DependencyProperty.Register("ChatRoomId", typeof(int), typeof(MKSelectPeriodForChatReportCW), new PropertyMetadata(0));
    public int ChatRoomId
    {
        get { return (int)GetValue(ChatRoomIdProperty); }
        set
        {
            SetValue(ChatRoomIdProperty, value);
        }
    }

    public static readonly DependencyProperty CurrentYearProperty = DependencyProperty.Register("CurrentYear", typeof(int), typeof(MKSelectPeriodForChatReportCW), new PropertyMetadata(0));
    public int CurrentYear
    {
        get { return (int)GetValue(CurrentYearProperty); }
        set
        {
            SetValue(CurrentYearProperty, value);
        }
    }

}

in XAML of MKSelectPeriodForChatReportCW I want to bind it's DependencyProperties to MKSelectMonthUC DependencyProperties like that:

<controls:ChildWindow x:Class="XX.mkControls.MKSelectPeriodForChatReportCW"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
       xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
       xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit" 
       xmlns:mk="clr-namespace:XX.mkControls.MKSelectPeriodForChatReport"
       Name="mainControl"
       >
<Grid x:Name="LayoutRoot" Margin="2">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>

    <mk:MKSelectMonthUC CurrentYear="{Binding CurrentYear, ElementName=mainControl}" ChatRoomId="{Binding ChatRoomId, ElementName=mainControl}" />


</Grid>

Properties on MKSelectPeriodForChatReportCW do get values (from their bindings) but values on MKSelectMonthUC don't. So please help me find a solution. Thanks.

I don't have all your source code and I cannot reproduce your problem, so all I can do is to make some suggestions based on the style of code you've presented above.

  1. As HiTechMagic says, the GetChatReport method call in the ChatRoomId setter in MKSelectMonthUC won't get called as often as you might expect. If you want a method to be called every time a dependency property changes, use a PropertyChangedCallback . This page on MSDN has an example of how to use a PropertyChangedCallback.

    For a property backed by a dependency property, the getter should only contain a call to GetValue and the setter should only contain a call to SetValue .

  2. Bindings using ElementName can be awkward to work with because they are silent if something goes wrong (eg no element with the given name was found). Presumably you have values for your CurrentYear and ChatRoomId properties somewhere in your view-model, and if so, I'd recommend binding both CurrentYear and both ChatRoomId dependency properties to data in your view-model.

  3. Bindings between two dependency properties are best used with presentation-layer information. For example, you might use a binding between two dependency properties to ensure two controls are the same width. The width of these controls is presentation-layer data since it isn't what data you're presenting, but it's how you're presenting it. Your CurrentYear and ChatRoomId properties are the data you're showing, not how you're showing it, so they're not presentation-layer data.

I would also recommend against giving top-level elements a Name or an x:Name and then using that name in a binding. Admittedly, the only XAML you've shown is your ChildWindow , so I don't know whether your MKSelectMonthUC user-control does the same. Nonetheless, for future reference, and for anyone else reading this answer, I'll give two reasons why this is a bad idea.

Suppose we have the following UserControl :

<UserControl x:Class="XYZ.MyUserControl"
             ....
             x:Name="myUc">
    <TextBlock Text="{Binding Path=MyProperty, ElementName=myUc}" />
</UserControl>

If we then attempt to use this control and give it a different x:Name , such as

<xyz:MyUserControl x:Name="abc123" />

we end up changing the name of the control from myUc to abc123 , and this breaks the binding.

Furthermore, if we attempt to use two or more of these user controls, for example

<StackPanel>
    <xyz:MyUserControl />
    <xyz:MyUserControl />
</StackPanel>

then we get an error about x:Name s not being unique, as both MyUserControl elements have an x:Name of myUc .

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