Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing elements of a User Control

Tags:

wpf

xaml

I have created a UserControl as follows:

<UserControl
x:Class="MySample.MyControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MySample"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">

<Canvas>

    <Ellipse Width="150" Height="150"/>

    <TextBlock>Sample</TextBlock>

</Canvas>

Now, from my main page I would want to change the Text appearing in my User Control from "Sample" to Hello World. So, I did this in my mainpage.xaml

<local:MyControl x:Name="MyControl" Margin="100,50 0,0"></local:MyControl>

And in the mainpage.xaml.cpp when I try to reference MyControl, it seems unrecognized:

MainPage::MainPage(){MyControl->Text = "Hello World";}

Any idea ?

like image 973
Frank Q. Avatar asked Apr 03 '12 03:04

Frank Q.


2 Answers

Detailing out @Steven You's answer, in your UserControl define a DependencyProperty. Defining a DependencyProperty allows change notifications to trigger updates to your controls.

In the code-behind of your UserControl you can add the dependency property.

public partial class MyUserControl : UserControl
{
    public string TextBlockText
    {
        get { return (string)GetValue(TextBlockTextProperty); }
        set { SetValue(TextBlockTextProperty, value); }
    }

    public static readonly DependencyProperty TextBlockTextProperty =
        DependencyProperty.Register("TextBlockText", typeof(string), typeof(MyUserControl), new UIPropertyMetadata(""));


    public MyUserControl()
    {
        InitializeComponent();
        DataContext = this;
    }
}

This exposes a public DependencyProperty which you can bind to in your UserControl's XAML.

<UserControl>
        <TextBlock Text="{Binding Path=TextBlockText}" />
</UserControl>

Now you need a way to set that property from your Window control. I'll detail three ways in which you can do this:

1.) Since the TextBlockText property is exposed on the UserControl we can set it directly in the XAML like:

<Window x:Class="WpfApplication2.MainWindow"
  xmlns:local="clr-namespace:WpfApplication2">
  <local:MyUserControl TextBlockText="Text that you want to set.">
  </local:MyUserControl>
</Window>

2.) If we give the UserControl a name we can change the property within the Window code-behind:

<Window x:Class="WpfApplication2.MainWindow"
  xmlns:local="clr-namespace:WpfApplication2">
  <local:MyUserControl Name="CoolUserControl">
  </local:MyUserControl>
</Window>

-

CoolUserControl.TextBlockText = "Text that you want to set.";

3.) Or lastly you can create another DependencyProperty within your Window's code-behind and bind it to the UserControl's dependency property. This way whenever you update the property the value within your Window code the UserControl dependency property will change too. This is the preferable choice as @Steven You said before, since your code behind does not need to know about any controls.

public partial class MainWindow : Window
{

    public string UserControlText
    {
        get { return (string)GetValue(UserControlTextProperty); }
        set { SetValue(UserControlTextProperty, value); }
    }

    public static readonly DependencyProperty UserControlTextProperty =
        DependencyProperty.Register("UserControlText", typeof(string), typeof(MainWindow), new UIPropertyMetadata(""));


    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
        UserControlText = "Text that you want to set.";
    }
}

And to bind to our new DependencyProperty in the Window XAML:

<Window x:Class="WpfApplication2.MainWindow"
        xmlns:local="clr-namespace:WpfApplication2">
    <local:MyUserControl TextBlockText="{Binding RelativeSource={RelativeSource AncestorType={x:Type Window}, Mode=FindAncestor}, Path=UserControlText}"></local:MyUserControl>
</Window>

Hope this helps!

like image 84
shanewwarren Avatar answered Oct 16 '22 20:10

shanewwarren


In program view, the best way to do this is using data binding rather than set the value in code behind. To solve this problem, the simplest way is to register a dependency property of the UserControl bind this value to the TextBlock and then set the value in MainPage.

like image 40
Steven You Avatar answered Oct 16 '22 21:10

Steven You