2012-10-24 87 views
3

假设这种情况:
我用DependencyProperty“SuperValue”创建了一个新的控件(“MyControl”)。
现在,在XAML我设置 “SuperValue” 到 “测试值”:从DependecyProperty绑定到XAML中的DataContext(ViewModel)

<local:MyControl SuperValue="TestValue" /> 

这种控制有一个ViewModel(DataContext的)。
我想将DependencyProperty的值(在本例中为“TestValue”)传递给ViewModel中的属性。

我该怎么做?

假设我的控件的ViewModel做了一些计算,例如:用户输入国家名称,控件给他一个当前的时间。

问题是:如何提供计算结果?假设这是ViewModel中的公共属性“结果”。我想创建一个像“TextBox.Text”,“ListView.SelectedItem”这样的属性,它将ViewModel数据的一部分提供给“外部”。

例如文本框和文本属性:

<TextBox Text={Binding GiveMeTextValue} /> 

在这种情况下DP“文本”提供了目前存储输入的文本一个ViewModel属性之外。

我想以相同的方式使用我的控件。

+0

我们可以在'无法设置'的情况下获得更多的上下文吗?你有什么尝试?您是否收到编译错误或运行时异常,或者当您期望它应用程序没有做任何事情? –

+0

这是你无法设置的MyDependencyProperty? –

+0

我添加了新的信息。 – Never

回答

1

怎么样设置MyDependencyProperty从属性 SomethingValueInDataContext

编辑

您可以设置在控制使用,而不是在其声明中的控制DependencyProperty。这将工作(本地命名空间是控制地方居住) -

<Grid> 
    <local:MyOwnControl MyDependencyProperty="{Binding Test}"/> 
</Grid> 

同你一样可以设置TextBoxWidth当您在XAML创建它的一个实例像这个 -

<TextBox Width="{Binding PropertyName}"/> 
+0

听起来不错,但使用MVVM拍打使视图模型(DataContext的),而并不知道什么查看我。 – Never

+0

好吧,你能否详细说明你为什么不能设置从查看你的'MyDependencyProperty'?这个DP在哪里? –

+0

我添加了新的信息。 :) – Never

1

公告,您的xaml的根目录是UserControl而不是MyOwnControl。 UserControl是MyOwnControl的基类;你的属性没有在基类中定义。这就是为什么您不能在UserControl的根元素内引用MyDependencyProperty

使用你的例子,你可以切换绑定并获得你想要的效果。

<UserControl 
    x:Class="namespace.MyOwnControl" 
    x:Name="root"> 
    <UserControl.DataContext> 
     <local:ControlViewModel 
      Test={Binding MyDependencyProperty, ElementName=root}" /> 
    </UserControl.DataContext> 
</UserControl> 
+1

它看起来不错,但我有错误:“绑定”不能在类型为“ControlViewModel”“测试”属性设置。 '绑定'只能在DependencyObject的DependencyProperty上设置。我可以尝试从ControlViewModel DependecyObject中创建,但我并不真正知道这是否是自然的,并且与MVVM一致? – Never

+0

@Never:是的。 'ControlViewModel'必须扩展'DependencyObject','Test'必须是'DependencyProperty'。我总是制作虚拟机的依赖对象。它使生活变得如此简单。另外,DP绑定是最快的绑定,因此您可以获得速度优势。它从来没有问题,直到它(几乎永远不会)。 – Will

+0

好的,所以我需要从DependencyObject中派生出来,并像我在我的问题中创建MyDependencyProperty一样使“Test”DP变得相同。 – Never

3

我不知道我是否可以得到你的问题的权利:你想在XAML静态的非绑定值设置为控件的一个DependencyProperty和控件的​​DataContext的一个属性设置为这个静态值?如果你需要这样做,你的概念有什么问题,你为什么不在ViewModel的相应字段中提供这个值,并将控件的DP绑定到这个字段?

但是,你可以做什么让你想要什么:

定义PropertyChangedCallback当您注册DP:

// Dependency Property 
public static readonly DependencyProperty TestProperty = 
DependencyProperty.Register("Test", typeof(string), 
typeof(MyControl), new FrameworkPropertyMetadata("123", new PropertyChangedCallback(OnTestChanged))); 

在OnTestChanged方法,投你的DataContext到的类型你ViewModel并将ViewModel上的相应值设置为新值:

private static void OnTestChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
     { 
      MyControl c = d as MyControl; 
      ViewModelType vm = c.DataContext as ViewModelType; 
      vm.Property = e.New; 
      Console.WriteLine(e.NewValue); 
     } 

这就是您所说的国王为?

+0

是的,这应该可以工作,但我不知道这是否与MVVM模式和组件分离规则100%一致。 – Never

+0

这不是MVVM。视图定义(XAML)不应包含“真实数据”,即以某种方式在逻辑中处理的数据。你想做什么?显然,您想要像XAML中那样定义一个值为“TestValue”的常量。你为什么不在ViewModel中定义常量,只是公开一个公共只读属性,它返回常量?然后,您可以将您的控件绑定到ViewModel的这个属性... – Marc

+0

不,这只是一个例子。我更新了我的问题。 – Never

1

由于您使用的是MVVM设计模式的所有数据应该是相对于视图模型。所以你的DP应该通过VM属性中的绑定来设置。

如果测试数据都在Blend/VS设计师使用,你可以检查该对调试/发布...然后做一些分配到基于关闭该检查测试你的财产。

+1

好的,但如何?我如何通过绑定到我的虚拟机属性来设置DP的值? – Never

1

您可以将一个属性添加到MyControl,名为InitialSuperValue,设置时设置值为SuperValue。然后写一些这样的XAML:

<local:MyControl InitialSuperValue="TestValue" SuperValue="{Binding SuperValueInViewModel, Mode=OneWayToSource}" /> 
+0

是的,它会工作,但每次当我使用控件时,写入“SuperValue =”{Binding SuperValueInViewModel,Mode = OneWayToSource}“”是一点疯狂的方法。 – Never

+0

同意。如果你想重复使用这个绑定逻辑(例如,在一个项目控件中的控件,它可能有#####的实例 - 或类似的情况),那么我建议模板化你的控件并设置绑定在模板中。 –

相关问题