【问题标题】:WPF Binding dynamic control in code behind to ViewModelWPF 将代码中的动态控件绑定到 ViewModel
【发布时间】:2012-07-06 07:17:34
【问题描述】:

我正在 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 路径错误:'Test' 在 'object' ''String' (HashCode=-946585093)' 上找不到属性。 绑定表达式:路径=测试; DataItem='String' (HashCode=-946585093); 目标元素是 'Button' (Name='');目标属性是“内容” (类型'对象')"

你能帮帮我吗?

【问题讨论】:

    标签: wpf dynamic controls code-behind


    【解决方案1】:

    您将UserControl1DataContext 属性设置为字符串,而不是您的视图模型实例。

    你需要做这样的事情:

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

    【讨论】:

    • 虽然所有答案都有效,但这对我来说是正确的答案,因为我有一个视图优先的方法,我不喜欢在后面的代码中设置数据绑定。非常感谢!
    【解决方案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 上)。并将XAML 中的DataContext 设置去掉类型。

    【讨论】:

      【解决方案3】:

      试试这个绑定

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

      【讨论】:

        【解决方案4】:

        max 是对的,但我还有一个问题。当您有要绑定的 viemwodel 时,为什么要创建用户控件动态?对我来说毫无意义。让我解释一下:

        如果你有一个视图模型 - 你知道这个视图模型应该如何呈现以及绑定是什么。所以你可以为这个视图模型创建一个用户控件/视图

        MyUserControl1View.xaml

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

        所以您现在拥有的是您的视图模型的表示。它们没有连接,但您的视图模型应该看起来像这样并且绑定已设置。到目前为止,根本没有设置任何数据上下文。

        您现在要做的就是采用视图模型优先方法并使用数据模板。

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

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

        现在 wpf 知道如何渲染 Usercontrol1viewmodel。

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

         public Usercontrol1viewmodel MyWhatEver {get;set;} 
        

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

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

        现在您在 contentpresenter 中看到了 MyUserControl1View,不需要动态视图代码。只需使用您的视图模型即可。

        ps:请随意编辑我糟糕的英语。

        【讨论】:

        • 在我的问题中,我只是解释了一个简单的例子。问题是,我有一个包含字段列表的项目列表。此字段列表是动态的。我迭代字段列表,为每个字段创建一个组合框或文本块并将其绑定到 ViewModel - 我仍在考虑如何完成最后一部分。感谢您的关注;)
        • np,当你写的字段是动态的 - 你真的是说对象(带有属性的视图模型)没有在设计时定义吗?只要你有一个定义的类型,你就可以轻松地使用我的方法。我不得不说在做 MVVM 时我真的不喜欢“查看优先”的方法(应用程序根/主窗口除外)
        • 我已经将我的问题阐述为一个问题本身(因为问题是从设计的角度而不是从实施的角度来看):stackoverflow.com/questions/11358669/…
        猜你喜欢
        • 1970-01-01
        • 2011-11-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-04
        • 1970-01-01
        相关资源
        最近更新 更多