1
votes

We have a TickerUserControl with a simple Text property which stands for the displayed text of the ticker.

  1. Do we really have to use these DependencyProperty pattern thing inside the UserControl (see below) or is there a simpler way to achieve this?

  2. When we want to use our UserControl and BIND the text field to a property of a ViewModel we have to use the following weird binding syntax. Why can't we just use 'Text="{Binding Text}"' like all the other controls? Is there something wrong with the property implementation of the UserControl or something?

Usage of the UserControl

<userControls:TickerUserControl Text="{Binding Path=Parent.DataContext.TickerText, RelativeSource={RelativeSource Self}, Mode=OneWay}"/>

Property implementation of the UserControl (code behind)

public partial class TickerUserControl : UserControl
{
    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); } 
    }

    public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(TickerUserControl), new PropertyMetadata(""));

    // ...
}

XAML snippet of the UserControl

<UserControl x:Class="Project.UserControls.TickerUserControl"
             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" 
             DataContext="{Binding RelativeSource={RelativeSource Self}}"
             mc:Ignorable="d">
    <TextBlock Text="{Binding Text}">

        <!-- ... -->     

The solution

The problem was the setting of the DataContext inside the UserControl. I deleted the DataContext binding added a name to the UserControl and modified the TextBox binding inside the UserControl. After that I was able to bind "as usual" from outside.

<userControls:TickerUserControl Text="{Binding TickerText}"/>

<UserControl x:Class="Project.UserControls.TickerUserControl"
             Name="TickerUserControl"
             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">
    <TextBlock Text="{Binding Text, ElementName=TickerUserControl}">

        <!-- ... -->
2

2 Answers

1
votes
  1. If you want to create bindable properties in the code behind of your UserControl, then yes, you do have to use DependencyProperty objects. However, you don't have to create your bindable properties there... you could use an MVVM type pattern and create your bindable properties in a separate class as long as you set that class as the DataContext of you UserControl.

  2. No, you don't have to use that 'weird' binding syntax... the problem is that you have hard coded setting the DataContext of your UserControl to its code behind. Instead of doing that, you can bind your Text DependencyProperty in the control like this:

    <TextBlock Text="{Binding Text, RelativeSource={RelativeSource FindAncestor, 
    {AncestorType={x:Type Local:TickerUserControl}}}" />
    

Local is the XML namespace of your local project... something like this:

     xmlns:Local="clr-namespace:Project.UserControls.TickerUserControl"

Then after removing the DataContext binding, you should be able to bind to the control from outside normally.

5
votes

If you want to bind your property, you'll need a dependency property.

To solve the weird binding you can do the following changes:

In your usercontrol

<UserControl Name="control"...
<TextBlock Text="{Binding Text, ElementName=control}">

And then you can bind it like that

<userControls:TickerUserControl Text="{Binding TickerText}"/>