0

I have created a UserControl with some fields. I would like to use it and bind data to these fields. Most of them are static values but the DataValue property comes from one property of the MainView. My code:

DataDisplayer.xaml
<UserControl x:Class="TabletMachineAccess.Controls.DataDisplayer"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:local="clr-namespace:TabletMachineAccess.Controls"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             x:Name="dataDisplayer"
             MaxHeight="100"
             mc:Ignorable="d">

    <Border Height="auto"
            Margin="5"
            Padding="5,2,5,2"
            BorderBrush="Gray"
            BorderThickness="2"
            CornerRadius="5">
        <StackPanel Orientation="Vertical">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding DataType}" />
                <TextBlock Text=":" />
            </StackPanel>
            <Separator Style="{StaticResource BasicSeparator}" />
            <TextBlock Margin="0,0,0,0"
                       HorizontalAlignment="Center"
                       FontWeight="Bold"
                       Text="{Binding Path=DataValue,
                                      ElementName=dataDisplayer}" />
            <StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
                <TextBlock FontWeight="ExtraLight" Text="(" />
                <TextBlock FontWeight="ExtraLight" Text="{Binding UnitText}" />
                <TextBlock FontWeight="ExtraLight" Text=")" />
            </StackPanel>
        </StackPanel>
    </Border>
</UserControl>
DataDisplayer.xaml.cs
public partial class DataDisplayer : UserControl
{
    public double DataValue
    {
        get { return (double)GetValue(DataValueProperty); }
        set { SetValue(DataValueProperty, value); }
    }

    // Using a DependencyProperty as the backing store for DataValue.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty DataValueProperty =
        DependencyProperty.Register("DataValue", typeof(double), typeof(DataDisplayer), new PropertyMetadata(9.9));

    public string DataType
    {
        get; set;
    }

    public string UnitText
    {
        get; set;
    }

    public DataDisplayer()
    {
        InitializeComponent();
        this.DataContext = this;
    }
}
I try to use it like this in MainView.xaml
 <controls:DataDisplayer Grid.Row="1"
    Grid.Column="0"
    DataType="{x:Static res:Strings.PVUpper}"
    DataValue="{Binding PVUpper}"
    UnitText="{x:Static res:Strings.KgUnit}" />
I have this in my MainViewModel.cs
public double PVUpper { get; set; }

For those properties, which get data from the res:Strings works fine and display the correct values, but DataValue property always shows the default value of the DependencyProperty (9.9). The value of PVUpper changes in every second in the ViewModel so I would like to see this change on the View as well.

dinci11
  • 13
  • 6
  • Do you get any Binding Errors in the output? You may want to check with some tool if the binding is correctly establishd and if the `DataContext` of your `DataDisplayer` is correct. – Ackdari Mar 31 '20 at 12:32
  • There is no Binding Error, the application runs fine but the value change does not visible on the screen. It is always `9.9`. – dinci11 Mar 31 '20 at 12:35
  • Ohh I think I see the error. You set the DataContext to `this` (in the constructor), but since the Binding for `DataValue` will be executed with the DataContex of `DataDisplayer ` there is no `PVUpper`-Property to bind onto. – Ackdari Mar 31 '20 at 12:43
  • So I should set the DataContext of the DataDisplayer in the MainView.xaml to MainView? If yes then how can I do this? – dinci11 Mar 31 '20 at 12:48

1 Answers1

0

The Problem is the wrong DataContex for the Binding. You set the DataContext-Property of your DataDisplayer to itself

public DataDisplayer()
{
    InitializeComponent();
    this.DataContext = this;
}

So the Binding DataValue="{Binding PVUpper}" tries to find a property with the name PVUpper on your DataDisplayer instance, which of course dose not succeed.

So you should not do this.DataContext = this; and just leave the DataContext untouched (your control will inherit the datacontext of its parent). You also will need to change the bindings in your DataDisplayer.xaml to address the changed DataContext.

But you can simplay add an ElementName=dataDisplayer to all the bindings to bind against your DataDisplayer instance.

So for example

<TextBlock FontWeight="ExtraLight" Text="{Binding UnitText}" />

becomes

<TextBlock FontWeight="ExtraLight" Text="{Binding UnitText, ElementName=dataDisplayer}" />
Ackdari
  • 3,222
  • 1
  • 16
  • 33
  • Thx, with this the binding is works fine, but the value on the screen is not changing when the value of `PVUpper` is changing. – dinci11 Mar 31 '20 at 13:05
  • You may need to add `Mode=OneWay` to the binding. I would recommend that you debug the property getter and setter to make sure that the values are actually changing (on both sides) and also to use a tool like Snoop to examin your UI – Ackdari Mar 31 '20 at 13:13