SeToY
SeToY

Reputation: 5895

Binding CustomControl to own properties

I'm driving myself nuts on this... I'm trying to provide my control with the simple ability to define an own color.

My control:

That's my xaml:

<Grid>
    <Grid.Resources>
        <ControlTemplate x:Key="starTemplate" TargetType="{x:Type ToggleButton}">
            <Viewbox>
                <Path x:Name="star"
                      Data="F1 M 145.637,174.227L 127.619,110.39L 180.809,70.7577L 114.528,68.1664L 93.2725,5.33333L 70.3262,67.569L 4,68.3681L 56.0988,109.423L 36.3629,172.75L 91.508,135.888L 145.637,174.227 Z"
                      Fill="LightGray" />
            </Viewbox>
            <ControlTemplate.Triggers>
                <Trigger Property="IsChecked" Value="True">
                    <Setter TargetName="star" Property="Fill" Value="Yellow" />
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </Grid.Resources>
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
        <ColumnDefinition />
        <ColumnDefinition />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <ToggleButton Grid.Column="0"
                  Click="RatingButtonClickEventHandler"
                  Cursor="Hand"
                  Tag="1"
                  Template="{StaticResource starTemplate}" />
    <ToggleButton Grid.Column="1"
                  Click="RatingButtonClickEventHandler"
                  Cursor="Hand"
                  Tag="2"
                  Template="{StaticResource starTemplate}" />
    <ToggleButton Grid.Column="2"
                  Click="RatingButtonClickEventHandler"
                  Cursor="Hand"
                  Tag="3"
                  Template="{StaticResource starTemplate}" />
    <ToggleButton Grid.Column="3"
                  Click="RatingButtonClickEventHandler"
                  Cursor="Hand"
                  Tag="4"
                  Template="{StaticResource starTemplate}" />
    <ToggleButton Grid.Column="4"
                  Click="RatingButtonClickEventHandler"
                  Cursor="Hand"
                  Tag="5"
                  Template="{StaticResource starTemplate}" />
</Grid>

Now when I bind the Path.Fill property like Fill="{Binding Path=UnselectedColor" I'd need to specify the DataContext of the control to itself:

public static readonly DependencyProperty SelectedColorProperty = DependencyProperty.RegisterAttached("SelectedColor", typeof(Brush), typeof(RatingControl), new UIPropertyMetadata(new SolidColorBrush(Colors.Yellow)));

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

This would work and I can define the color from my control, but it would destroy any other bindings.

Back from the custom control to my implementation:

For example the following code would set the SelectedColor and UnselectedColor, but the binding of RatingValue="{Binding Path=Rating} would fail since it tries to bind to property Rating in my RatingControl instead of the property in my ViewModel.

<my:RatingControl Grid.Row="0"
                  Grid.Column="0"
                  HorizontalAlignment="Left"
                  VerticalAlignment="Center"
                  IsReadOnly="True"
                  RatingValue="{Binding Path=Rating,
                                        TargetNullValue='0.0',
                                        Mode=TwoWay}"
                  SelectedColor="Orange"
                  ToolTip="Bewertung"
                  UnselectedColor="LightGray" />

That's the binding error. Extension is a property in my ViewModel and it contains a double property Rating that I'm trying to bind:

System.Windows.Data Error: 40 : BindingExpression path error: 'UnselectedColor' property not found on 'object' ''Extension' (HashCode=24138614)'. BindingExpression:Path=UnselectedColor; DataItem='Extension' (HashCode=24138614); target element is 'Path' (Name=''); target property is 'Fill' (type 'Brush')

Upvotes: 2

Views: 681

Answers (3)

Thien Nguyen
Thien Nguyen

Reputation: 41

When you do this

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

you bound DataContext of RatingControl to itself and every databinding on your control, if no change of dataContext later happens, will bind to RatingControl's properties. That's why the Rating binding doens't work (there is no Rating in RatingControl). I think you should remove DataContext = this; in RatingControl's constructor, and try to bind Fill property to SelectedColor property of RatingControl with following code on RatingControl XAML:

Fill="{Binding ElementName=<nameOfRatingControl>, SelectedColor}"

This link would help you have an overview about dataBinding: http://www.wpftutorial.net/DataBindingOverview.html. Hope this help.

Upvotes: 1

LPL
LPL

Reputation: 17083

You are setting the DataContext in the wrong manner. Please read Simple Pattern for Creating Re-useable UserControls.

For short it should be

<Grid x:Name="LayoutRoot">

and

public RatingControl()
{
    InitializeComponent();
    LayoutRoot.DataContext = this;
}

Upvotes: 1

Athari
Athari

Reputation: 34293

When you need to bind to self, you can use Binding.RelativeSource Property.

See also:

Upvotes: 0

Related Questions