Reputation: 14982
Not sure if what I want is possible, but I also wouldn't know why it isn't.
I have a user control with a dependency property (a string
) which I define in XAML e.g. as follows:
<Window ... (EngraveUnitWindow)
DataContext = EngraveUnitViewModel
...
...
<parameters:DoubleParameterUserControl
DisplayName="Exchanger Offset [deg]"
DataContext="{Binding ExchangerOffset}"/>
The view model 'EngraveUnitViewModel' :
public class EngraveUnitViewModel : ViewModelBase, IUnitViewModel
...
...
public DoubleParameterViewModel ExchangerOffset { get; }
What I want to achieve, is set the value of DisplayName
to ParameterName
property in the DoubleParameterViewModel
. So I created a Style
which binds the DisplayName
to the viewmodel as follows:
<UserControl.Resources>
<Style TargetType="parameters:DoubleParameterUserControl">
<Setter Property="DisplayName" Value="{Binding ParameterName, Mode=OneWayToSource}"/>
</Style>
</UserControl.Resources>
The complete DoubleParameterUserControl
code below:
<UserControl
...
...
d:DataContext="{d:DesignInstance viewModels:DoubleParameterViewModel, d:IsDesignTimeCreatable=False}"
Margin="5">
<UserControl.Resources>
<Style TargetType="parameters:DoubleParameterUserControl">
<Setter Property="DisplayName" Value="{Binding ParameterName, Mode=OneWayToSource}"/>
</Style>
</UserControl.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding ElementName=DoubleParameter, Path=DisplayName}" VerticalAlignment="Center" Margin="5,0,0,0" />
<Border Grid.Column="1" BorderThickness="1" BorderBrush="LightGray" Margin="0, 0, 5, 0">
<TextBlock
VerticalAlignment="Center"
Text="{Binding Value, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
Margin="5, 0, 5, 0">
<TextBlock.InputBindings>
<MouseBinding Gesture="LeftClick" Command="{Binding ShowNumpadCommand}" />
</TextBlock.InputBindings>
</TextBlock>
</Border>
<Button x:Name="_button" Grid.Column="2" MinWidth="30" MinHeight="30" Content="..." Command="{Binding ShowNumpadCommand}"/>
</Grid>
</UserControl>
And its code behind (where I define the DependencyProp:
public partial class DoubleParameterUserControl
{
public string DisplayName
{
get => (string)GetValue(DisplayNameProperty);
set => SetValue(DisplayNameProperty, value);
}
public static readonly DependencyProperty DisplayNameProperty =
DependencyProperty.Register(nameof(DisplayName), typeof(string), typeof(DoubleParameterUserControl),
new PropertyMetadata(""));
public DoubleParameterUserControl()
{
InitializeComponent();
_button.Focus();
}
}
For completeness, the viewmodel:
public class DoubleParameterViewModel : ViewModelBase
{
private readonly Parameter<double> parameter;
private double value;
public RelayCommand ShowNumpadCommand { get; }
public string ParameterName { get; set; }
public double Value
{
get => parameter.Value;
set
{
parameter.Value = value;
Set(() => Value, ref this.value, value);
}
}
public DoubleParameterViewModel(Parameter<double> parameter)
{
this.parameter = parameter;
ShowNumpadCommand = new RelayCommand(ShowNumpad);
}
private void ShowNumpad()
{
var numpadViewModel = new VirtualKeypadsViewModel(true)
{
ParameterName = ParameterName,
Input = Value.ToString("F2", CultureInfo.InvariantCulture)
};
var numpad = new Numpad
{
Owner = System.Windows.Application.Current.MainWindow,
DataContext = numpadViewModel
};
if (numpad.ShowDialog() == true)
{
Value = numpadViewModel.ResultAsDouble();
}
}
}
Just to be clear, the property ParameterName
in the ViewModel never gets set. So in my code, I want to popup a Numpad dialog which shows the parameter name in its title bar, but the ParameterName did not receive the bound DisplayName.
I hope somebody can explain me how I can solve that. (or, that it is not possible, and why not if that would sadly be the case)
Upvotes: 0
Views: 924
Reputation: 25623
It seems like DoubleParameterViewModel.ParameterName
exists solely to provide a name when executing ShowNumpadCommand
. If that's the case, forget the property and just pass DisplayName
as your command parameter.
public ICommand ShowNumpadCommand { get; }
public DoubleParameterViewModel(Parameter<double> parameter)
{
this.parameter = parameter;
ShowNumpadCommand = new RelayCommand<string>(ShowNumpad);
}
private void ShowNumpad(string parameterName)
{
/* ... */
}
Get rid of the Style
, and bind your button's command parameter to its owner's DisplayName
:
<UserControl x:Name="EditorRoot">
<!-- ... -->
<Button x:Name="_button"
Command="{Binding ShowNumpadCommand}"
CommandParameter="{Binding ElementName=EditorRoot, Path=DisplayName}" />
<!-- ... -->
</UserControl>
Upvotes: 2