0

In my project I have two custom user controls. One simple numeric control called NumericUpDown. And a numeric control grid called NumericUpDownGrid. Both have defined dependency properties as follows:

For the NumericUpDown the XAML code is:

<Grid>
        <Grid>
            <StackPanel Orientation="Horizontal">
                <TextBox x:Name="txtNum" x:FieldModifier="private" Margin="5,5,0,5" Width="50" Text="{Binding Value,Mode=TwoWay}"/>
                <Button x:Name="cmdUp" x:FieldModifier="private" Margin="5,5,0,5" Content="˄" Width="20" Click="cmdUp_Click" />
                <Button x:Name="cmdDown" x:FieldModifier="private" Margin="0,5,0,5"  Content="˅" Width="20" Click="cmdDown_Click" />
            </StackPanel>
        </Grid>
    </Grid>

And the C# property defined as follows:

public static readonly DependencyProperty ValueDependencyProperty = DependencyProperty.Register("Value", typeof(double), typeof(NumericUpDown));

public double Value {
    get { return (double)GetValue(ValueDependencyProperty); }
    set { SetValue(ValueDependencyProperty, value); }
}

public NumericUpDown() {
    InitializeComponent();
    Value = 0.0;
    this.DataContext = this;
}

Based on the above simple control I need to make a grid of those controls. However instead of resolving each element I can bind an array of values so that I don't have to code all the updates.

Therefore the code for a grid of those components is the following:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition />
    </Grid.RowDefinitions>

    <StackPanel Grid.Row="0" Grid.Column="0" Orientation="Horizontal">
        <Label Width="20">A</Label>
        <control:NumericUpDown x:Name="A" Value="{Binding Values[0],Mode=TwoWay}"></control:NumericUpDown>
    </StackPanel>
    <StackPanel Grid.Row="0" Grid.Column="1" Orientation="Horizontal">
        <Label Width="20">B</Label>
        <control:NumericUpDown x:Name="B" Value="{Binding Values[1],Mode=TwoWay}"></control:NumericUpDown>
    </StackPanel>
    <StackPanel Grid.Row="0" Grid.Column="2" Orientation="Horizontal">
        <Label Width="20">C</Label>
        <control:NumericUpDown x:Name="C" Value="{Binding Values[2],Mode=TwoWay}"></control:NumericUpDown>
    </StackPanel>
</Grid>

Similarly the C# code for the dependency property and the constructor is:

public static readonly DependencyProperty ValuesDependencyProperty = DependencyProperty.Register("Values", typeof(double[]), typeof(NumericUpDownGrid));
public double[] Values {
    get { return (double[])GetValue(ValuesDependencyProperty); }
    set { SetValue(ValuesDependencyProperty, value); }
}

public NumericUpDownGrid() {
    Values = new double[] { 0.5, 0.0, 0.0 };
    InitializeComponent();
    this.DataContext = this;
}

Now I would expect that when I push either the cmdUp or cmdDown button, the value change inside the single NumericUpDown would be reflected in the relevant array of my NumericUpDownGrid. Since those are bounded. But this is not the case. Any help would be much appreciated.

I need this since will binding this NumericUpDownGrid to data from my application higher up the chain. I am expecting that this binding will propagate downwards to a single element when bound. Additionally any change by a single NumericUpDown should be propagated back to the array used at a higher level.

msmechanized
  • 436
  • 4
  • 19
  • `Text="{Binding Value, RelativeSource={RelativeSource TemplatedParent}}"` – aepot Aug 22 '20 at 21:58
  • That's wrong. It must be `Text="{Binding Value, RelativeSource={RelativeSource AncestorType=UserControl}}` (assuming it is a UserControl), and you have to remove the DataContext assignment `this.DataContext = this;`. If you explicitly set the DataContext like this, a Binding like `` expects the `Values` source property in the NumericUpDown control. – Clemens Aug 22 '20 at 22:11
  • @Clemens could please elaborate or point me out to a documentation source? – msmechanized Aug 22 '20 at 22:59
  • The elaboration is in the answers of the marked duplicate questions - and several other similiar ones. For the DataContext in general, there is online documentation. In case you found `DataContext = this;` in a blog post or tutorial, be aware that there is a lot of garbage on the internet. A valid place for an explicit assignment of the DataContext is in a Window or Page. In a control, it is always wrong, because it break DataContext-based bindings of the control's properties. – Clemens Aug 23 '20 at 08:04

0 Answers0