WPF将代码中的动态控件绑定到ViewModel

时间:2012-07-06 07:17:34

标签: wpf dynamic controls code-behind

我正在WPF中构建自定义UserControl,它与ViewModel相关联。我也想在后面的代码中动态制作控件。但是现在我遇到了将生成的控件与ViewModel属性绑定的问题。我的代码是:

<UserControl x:Class="SVT.Teste.UserControl1"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300"
             DataContext="UserControl1ViewModel">
    <Grid Name="GridContainer">
    </Grid>
</UserControl>

和代码背后:

    public UserControl1()
    {
        InitializeComponent();
        System.Windows.Controls.Button newBtn = new Button();
        newBtn.SetBinding(Button.ContentProperty, new Binding("Test"));
        GridContainer.Children.Add(newBtn);
    }

    public class UserControl1ViewModel
    {
        private string test = "ola";

        public string Test
        {
            get { return test; }
        }
    }

当我跑步时,我得到:

  

“System.Windows.Data错误:40:BindingExpression路径错误:'测试'   在'object'''String'(HashCode = -946585093)'上找不到属性。   BindingExpression:路径=测试; DataItem ='String'(HashCode = -946585093);   target元素是'Button'(Name ='');目标属性是'内容'   (输入'对象')“

你能帮助我吗?

4 个答案:

答案 0 :(得分:2)

您正在将DataContext UserControl1属性设置为字符串而不是视图模型实例。

你需要做这样的事情:

<UserControl xmlns:local="clr-namespace:NAMESPACE_WHERE_VIEWMODEL_IS_DEFINED">
    <UserControl.DataContext>
        <local:UserControl1ViewModel />
    </UserControl.DataContext>
    <!-- unrelated code omitted -->
</UserControl>

答案 1 :(得分:2)

您正在将DataContext设置为该类型,而不是具有该属性的实例。 在创建用户控件的方法中执行:

          public UserControl1()
        {
            InitializeComponent();
            System.Windows.Controls.Button newBtn = new Button();
            newBtn.SetBinding(Button.ContentProperty, new Binding("Test"));
            GridContainer.Children.Add(newBtn);
            **DataContext = new UserControl1ViewModel();**
        }

你还有很多工作要做。你没有通知或更新的方式将会发生。实现INotifyPropertyChanged接口(在UserControlViewModel上)。并将DataContext中的XAML设置为类型。

答案 2 :(得分:1)

尝试使用此绑定

Binding MyBinding = new Binding();
MyBinding.Path = new PropertyPath("Test");
newBtn.DataContext = new UserControl1ViewModel(); //or MyBinding.Source = new //UserControl1ViewModel();


newBtn.SetBinding(Button.ContentProperty, MyBinding);

答案 3 :(得分:0)

max是对的,但我有另一个问题。当你想要绑定到viemwodel时,为什么要创建你的usercontrol动态?对我毫无意义。让我解释一下:

如果你有一个viewmodel - 你知道应该如何呈现这个viewmodel以及绑定是什么。所以你可以为这个viewmodel

创建一个usercontrol / view

MyUserControl1View.xaml

<UserControl>
 <Grid>
   <Button Content="{Binding Test}"/>
   <!-- more controls and binding if the viewmodel expose more-->
 </Grid>
</UserControl>

所以你现在拥有的是viewmodel的表示。它们没有连接,但你的viewmodel应该看起来像这样,绑定设置。到目前为止,根本没有设置任何datacontext。

现在你要做的就是先使用viewmodel方法并使用datatemplates。

让我们在主窗口中假设以下内容

<Window>
 <Window.Resources>
  <DataTemplate Datatype="{x:Type local:Usercontrol1viewmodel}">
    <view:MyUserControl1View/>
  </DataTemplate>
 </Window.Resources>

现在wpf知道如何渲染Usercontrol1viewmodel。

在您的主窗口视图模型中再处理一次Usercontrol1viewmodel。

 public Usercontrol1viewmodel MyWhatEver {get;set;} 

如果将此属性绑定到contentpresenter,您将看到wpf magic;)

 <ContentPresenter Content="{Binding MyWhatEver}"/>

现在您在contentpresenter中看到MyUserControl1View,不需要动态视图代码。只需使用你的viewmodels。

ps:随意编辑我的坏英语。