Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to expose internal control's property to its parent UserControl in WPF

I have a DialogPrompt UserControl that will have an Image and a TextBlock. Here is the template:

    <UserControl>   
      <Button x:Name="_OkButton" Content="OK"/>
      <DockPanel >
        <Image/>
        <TextBlock x:Name="_DialogTextBox" />
      </DockPanel>
    </UserControl>

How do I expose Source property of the Image and Text property of the TextBlock inside my UserControl?

like image 540
eYe Avatar asked May 14 '15 14:05

eYe


2 Answers

I would create two DependencyProperties, one for the Text and one for the Image Source.

The Image Source DependencyProperty will automatically set the inner Image control's source whenever it is updated. Similarly, the Text DependencyProperty will be setting the Text of the inner TextBlock control as well.

Here is the setup:

public partial class MyUserControl : UserControl
{
    #region ImageSource
    public static readonly DependencyProperty ImageSourceProperty = 
        DependencyProperty.Register
        ( 
            "ImageSource", 
            typeof(Uri),
            typeof(MyUserControl), 
            new FrameworkPropertyMetadata(new PropertyChangedCallback(OnImageSourceChanged))
        );

    public Uri ImageSource
    {
        get { return (Uri)GetValue(ImageSourceProperty); }
        set { SetValue(ImageSourceProperty, value); }
    }
    #endregion ImageSource

    #region Text
    public static readonly DependencyProperty TextProperty = 
        DependencyProperty.Register
        ( 
            "Text", 
            typeof(string),
            typeof(MyUserControl), 
            new FrameworkPropertyMetadata("")
        );

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }
    #endregion Text

    public MyUserControl()
    {
        InitializeComponent();
    }

    private static void OnImageSourceChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        var myUserControl = sender as MyUserControl;
        if (myUserControl != null)
        {
            myUserControl.ImageSource.Source = new BitmapImage((Uri) e.NewValue);
        }
    }
} 

Whenever the Image Source changes, this will automatically update the source of the inner Image control. Note, we need to do some conversion here since the Image control itself uses an ImageSource type.

XAML can then be updated to:

   <UserControl x:Name="ControlName">   
      <Button x:Name = "OkButton" Content="OK"/>
      <DockPanel >
        <Image x:Name = "MyImage" />
        <TextBlock x:Name = "DialogTextBox" Text="{Binding ElementName=ControlName, Path=Text}"/>
      </DockPanel>
    </UserControl>

Here, the inner TextBlock control simply binds to the Text DependencyProperty of the parent (the main UserControl).

like image 107
d.moncada Avatar answered Sep 20 '22 00:09

d.moncada


In your code behind, add 2 DependencyProperties and bind them to your Image Source and to your TextBlock Text.

Here is a tutorial on how to use and create Dependency Properties : http://www.wpftutorial.net/dependencyproperties.html

For your binding in your xaml, here is an example :

<Image Source="{Binding YourProperty, RelativeSource={RelativeSource FindAncestor, AncestorType=YourUserControl}}/>
like image 40
mgarant Avatar answered Sep 24 '22 00:09

mgarant