2017-09-14 153 views
0

不知道我想要的是否可能,但我也不知道它为什么不是。将DependencyProperty的值设置为ViewModel属性

我有我在XAML中定义的依赖属性(一个string)的用户控件,例如如下:

<Window ... (EngraveUnitWindow) 
    DataContext = EngraveUnitViewModel 
    ... 
    ... 

    <parameters:DoubleParameterUserControl 
     DisplayName="Exchanger Offset [deg]" 
     DataContext="{Binding ExchangerOffset}"/> 

视图模型 'EngraveUnitViewModel':

public class EngraveUnitViewModel : ViewModelBase, IUnitViewModel 
    ... 
    ... 
    public DoubleParameterViewModel ExchangerOffset { get; } 

我想达到的目标,是集DisplayNameParameterName财产在DoubleParameterViewModel价值。所以,我创建了一个Style结合的DisplayName到视图模型如下:

<UserControl.Resources> 
    <Style TargetType="parameters:DoubleParameterUserControl"> 
     <Setter Property="DisplayName" Value="{Binding ParameterName, Mode=OneWayToSource}"/> 
    </Style> 
</UserControl.Resources> 

下面的完整DoubleParameterUserControl代码:

<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> 

而其背后的代码(这里我定义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(); 
    } 
} 

为了完整,视角模型:

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(); 
     } 
    } 
} 

要清楚,ViewModel中的属性ParameterName永远不会被设置。所以在我的代码中,我想要弹出一个Numpad对话框,在其标题栏中显示参数名称,但是ParameterName没有收到绑定的DisplayName。

我希望有人能解释我如何解决这个问题。 (或者说,这是不可能的,以及为什么不这样做,如果可悲的情况下)

+0

什么'ExchangerOffset'?那是'DoubleParameterViewModel'吗? –

+0

您的VisualStudio输出中是否有任何System.Data.Error? – sTrenat

+0

@EdPlunkett对不起,错过了一个,是的,这是正确的。我更新了这个问题 – bas

回答

2

看起来像DoubleParameterViewModel.ParameterName存在只提供一个名称,当执行ShowNumpadCommand。如果是这种情况,请忘记该属性,并将DisplayName作为命令参数。

public ICommand ShowNumpadCommand { get; } 

public DoubleParameterViewModel(Parameter<double> parameter) 
{ 
    this.parameter = parameter; 
    ShowNumpadCommand = new RelayCommand<string>(ShowNumpad); 
} 

private void ShowNumpad(string parameterName) 
{ 
    /* ... */ 
} 

摆脱Style的,和你的按钮的命令参数绑定到其拥有者的DisplayName

<UserControl x:Name="EditorRoot"> 
    <!-- ... --> 
    <Button x:Name="_button" 
      Command="{Binding ShowNumpadCommand}" 
      CommandParameter="{Binding ElementName=EditorRoot, Path=DisplayName}" /> 
    <!-- ... --> 
</UserControl> 
+0

哦,我的....那真是太棒了!奇迹般有效!谢谢! – bas

+0

很高兴帮助。如果您对此解决方案感到满意,我会很高兴您接受我的答案。 –

+0

好吧,我想等一下,更多的人会去拜访(也许还会奖励你:))。一旦我达到成功,仍然重构你的修复我绝对会接受答案 – bas