【问题标题】:How to bind a property in the view model of a usercontrol to a property in another usercontrol如何将用户控件的视图模型中的属性绑定到另一个用户控件中的属性
【发布时间】:2014-02-04 15:25:24
【问题描述】:

我目前正在使用 MVVM 在 WPF 用户控件中工作。我的 MainWindow.xaml 如下所示。

MainWindow.xaml

<Window.Resources>
    <ObjectDataProvider x:Key="TabsList" ObjectType="{x:Type local:MainWindowModel}" MethodName="GetTabs"/>
</Window.Resources>
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <ListBox Grid.Column="0"  ItemsSource="{Binding Source={StaticResource TabsList}}" IsSynchronizedWithCurrentItem="True">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Label Content="{Binding Path=TabName}" Margin="10"/>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    <ContentControl Grid.Column="1" Content="{Binding Source={StaticResource TabsList}, Path=MyUserControl}"/>
</Grid>

数据提供者类如下

public class MainWindowModel
{
    public List<TabInfo> GetTabs()
    {
        return new List<TabInfo>()
        {
            new TabInfo() { TabName="Tab1", MyUserControl = new UserControl1()},
            new TabInfo() { TabName="Tab2", MyUserControl = new UserControl2()}
        };
    }
}
 public class TabInfo
{
    public string TabName { get; set; }
    public UserControl MyUserControl { get; set; }
}

现在我有两个用户控件 UserControl1 和 UserControl2 每个都有一个文本框控件。每当更新 UserControl2 中 Textbox 控件的 Text 属性时,我想更新 UserControl1 中文本框控件的 Text 属性。为此,我尝试如下。

用户控件1

<UserControl x:Class="MoreOnBinding2.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">
<Grid>
    <TextBox Width="200" Height="20" Text="{Binding Path=UserControl1Text}"/>
</Grid>

UserControl1ViewModel

public class UserControl1VM : ViewModelBase
{
    public UserControl1VM()
    {
        this.UserControl1Text = "10";
    }
    private string userControl1Text;

    public string UserControl1Text
    {
        get { return userControl1Text; }
        set
        {
            if (userControl1Text != value)
            {
                userControl1Text = value;
                RaisePropertyChanged(() => UserControl1Text);
            }
        }
    }

}

用户控件2

<UserControl x:Class="MoreOnBinding2.UserControl2"
         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" 
         xmlns:local="clr-namespace:MoreOnBinding2"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<Grid>
    <TextBox Width="200" Height="20" 
        Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:UserControl1}}, 
        UpdateSourceTrigger=PropertyChanged, Path=UserControl1Text}" />
</Grid>

但它不起作用。 UserControl2 中的RelativeSource 标记似乎有问题。有人可以帮忙吗?

【问题讨论】:

  • UserControl1 当然不是 UserControl2 的祖先。发布您在窗口中放置这两个用户控件的结构。
  • 您的视图模型中有UserControl 类型的属性?请删除那个 MVVM 标签...你不应该使用它。
  • @RohitVats 我在上面发布的 MainWindow.xaml 中的 ContentControl 包含用户控件。我还发布了 MainWindowModel 类,我在其中实例化了用户控件。让我知道,如果需要更多。我已经发布了上面所有的代码。
  • @Sheridan 你能建议我在上述情况下避免视图模型中的用户控件引用吗?对示例代码的任何引用都可能对我有很大帮助。
  • @Rahul,您不需要示例代码,您需要 MVVM 教育。您声称使用 MVVM,但您显然不知道它是什么。我建议简单地阅读它,或者停止假装你正在使用它。主要思想是将您的数据和视图分开,但是通过将视图元素放入您的数据提供程序类中,您在第一个障碍中就失败了。有很多在线教程。

标签: c# wpf xaml mvvm user-controls


【解决方案1】:

您可以在用户控件上使用依赖属性,这将为您提供可绑定的属性。见link

编辑 1

再次查看了您的课程设置。如果您遵循 MVVM 方法,我认为您不应该在视图模型中引用您的用户控件

View Model 应该更像Like

public Class
{
   ObservableCollection<TabInfo> _Tabs = new ObservableCollection<TabInfo>();
   public ObservableCollection<TabInfo> Tabs
   {
     get{return _Tabs;}
     set {_Tabs = value;}//Need to implement INotifyPropertyChanged [Link][2]
   }

   public TabInfo SelectedTab {get;set;}
}

public class TabInfo
{
    public string TabName { get; set; }
    public UserControlViewModel MyUserControlViewModel{ get; set; }
} 

然后在你的视野中

<Window.DataContext>
    <vm:MainWindowModel />
</Window.DataContext>
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <ListBox Grid.Column="0"  ItemsSource="{Binding Tabs}" IsSynchronizedWithCurrentItem="True" SelectedValue="{Binding SelectedTab}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Label Content="{Binding Path=TabName}" Margin="10"/>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    <ContentControl Grid.Column="1" Content="{Binding SelectedTab.MyUserControlViewModel"/>
</Grid>

This should give you a list of Tabs and then when one is selected it will set the content of the ContentControl to the MyUserControlViewModel.

然后您需要使用某种模板选择器来控制 ContentTemplate 以将不同的 UserControls 加载到 ContentControl 中

我尚未测试代码是否有效,您需要在所有公共属性上实现 INotifyPropertyChanged,以便绑定随着属性值的更改而更新。

希望能有所帮助。

【讨论】:

  • 当我单击列表框项时,绑定属性“SelectedTab.MyUserControlViewModel”会给出 ViewModel 的 ToString() 值,而不是显示视图。如果我在这里遗漏了什么,请您解释一下。谈到我原来的问题,我已经按照您在每个用户控件中的建议添加了一个依赖属性,但我不明白如何将 usercontrol2 的依赖属性与 usercontrol1 的视图模型中的属性绑定。你能解释一下吗?
  • 现在我明白了。我错过了在资源中定义数据模板。指定以下内容后,我可以按照您的建议更改为完整的 MVVM 模式。谢谢你的帮助。
猜你喜欢
  • 1970-01-01
  • 2013-04-20
  • 2015-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-24
  • 1970-01-01
相关资源
最近更新 更多