WPF 用户控件的多个实例都使用相同的 ViewModel [英] Multiple instances of a WPF user control all use the same ViewModel

查看:100
本文介绍了WPF 用户控件的多个实例都使用相同的 ViewModel的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个应用程序,当我单击一个按钮时,它会加载一个带有 UserControl 的新 TabItem.这工作正常,但是...当我再次单击添加"按钮时,另一个 TabItem 添加了一个新的 UserControl 实例.问题来了.当我在 tab1 中添加一些数据并切换到 tab2 时,我也会在那里看到输入的数据.这怎么可能?我为每个 UserControl 使用一个新的 ViewModel,那么 tab1 和 tab2 上的用户控件如何显示相同的数据.它可能会很愚蠢,但我找不到它......

I have an app that when I click a button loads a new TabItem with a UserControl. This works fine, but... When I click the Add button again, another TabItem is added with a new instance of the UserControl. Here comes the problem. When I add some data in tab1 and switch to tab2, I also see the entered data there. How is this possible? I use a new ViewModel for each UserControl so how can both user controls on tab1 and tab2 show the same data. It will probably be something stupid, but I can't find it...

结构是这样的:MainWindow 加载一个 UserControl,上面只有一个 TabControl.单击菜单中的添加按钮后,将添加一个新的 TabItem,并在其上添加一个新的 UserControl.

Structure is like this: MainWindow loads a UserControl with only a TabControl on it. After clicking an Add button in the menu a new TabItem is added with a new UserControl on it.

SO 上有一些看起来像这样但不同的问题.

There are here on SO some issues that look like this but are different.

这是一些代码.

TabControl.xaml:

<Grid>
    <TabControl x:Name="tabControl" ItemsSource="{Binding TabItems}" SelectedIndex="0">
        <TabControl.Resources>
            <DataTemplate DataType="{x:Type ViewModel:OverviewViewModel}">
                <my:OverviewControl />
            </DataTemplate>
            <DataTemplate DataType="{x:Type ViewModel:MemberViewModel}">
                <my:MemberControl />
            </DataTemplate>
        </TabControl.Resources>
        <TabControl.ItemContainerStyle>
            <Style TargetType="TabItem">
                <Setter Property="Header" Value="{Binding Header}" />
            </Style>
        </TabControl.ItemContainerStyle>
    </TabControl>
</Grid>

TabControl.cs:

public TabControl()
{
    InitializeComponent();
    this.DataContext = new TabViewModel(true);
}

TabViewModel 有一个保存 TabItems 的 DP:

TabViewModel has a DP which holds the TabItems:

public static readonly DependencyProperty TabItemsProperty =
    DependencyProperty.Register(
    "TabItems", typeof(ObservableCollection<ITabViewModel>), typeof(TabViewModel),
    new UIPropertyMetadata(new ObservableCollection<ITabViewModel>()));
public ObservableCollection<ITabViewModel> TabItems
{
    get { return (ObservableCollection<ITabViewModel>)GetValue(TabItemsProperty); }
    set { SetValue(TabItemsProperty, value); }
}

加载在 TabItemMemberControl.cs 上的 UserControl:

public MemberControl()
{
  InitializeComponent();
    this.DataContext = new MemberViewModel{};
}

MemberControlViewModel:

private MemberModel _memberModel = new MemberModel();

public MemberViewModel()
{
  Address = new AddressViewModel();
}

public static readonly DependencyProperty FirstNameProperty =
    DependencyProperty.Register("FirstName", typeof(string), typeof(MemberViewModel),
    new UIPropertyMetadata(string.Empty, OnFirstNameChanged));
public string FirstName
{
    get { return (string)GetValue(FirstNameProperty); }
    set { SetValue(FirstNameProperty, value); }
}

public static void OnFirstNameChanged(DependencyObject m,
    DependencyPropertyChangedEventArgs e)
{
    var d = m as MemberViewModel;
    if (d._memberModel != null)
        d._memberModel.FirstName = d.FirstName;
}

public static readonly DependencyProperty LastNameProperty =
    DependencyProperty.Register("LastName", typeof(string), typeof(MemberViewModel),
    new UIPropertyMetadata(string.Empty, OnLastNameChanged));
public string LastName
{
    get { return (string)GetValue(LastNameProperty); }
    set { SetValue(LastNameProperty, value); }
}

public static void OnLastNameChanged(DependencyObject m,
    DependencyPropertyChangedEventArgs e)
{
    var d = m as MemberViewModel;
    if (d._memberModel != null)
        d._memberModel.LastName = d.LastName;
}

然后最后我菜单上的命令实际上将 MemberControl 添加为 TabControl 上的新 TabItem:

And then at last the Command on my menu that actually adds the MemberControl as an new TabItem on the TabControl:

private void LoadNewMember(object notUsed)
{
    _tabViewModel.TabItems.Add(new MemberViewModel { Header = "New Member" });
    _addOverview.RaiseCanExecuteChanged();
}

我在绑定过程中的某个地方做错了,但如上所述,我找不到它.

Somewhere along the way I do something wrong with the binding, but as said, I can't find it.

感谢您的帮助.

推荐答案

您似乎将每个 MemberControl 的 DataContext 设置了两次.

You appear to be setting the DataContext of each MemberControl twice.

一旦您将 MemberViewModel 添加到您的选项卡集合中:

Once when you add the MemberViewModel to your tab collection:

_tabViewModel.TabItems.Add(new MemberViewModel { Header = "New Member" });

由于您设置了 DataTemplate,这将创建一个 MemberControl.

this will create a MemberControl due to the DataTemplate you have set up.

然后,在您的 MemberControl 的构造函数中,您将 DataContext 重置为 MemberViewModel 的新实例:

Then, in your MemberControl's constructor you then reset the DataContext to a new instance of MemberViewModel:

public MemberControl()
{
    InitializeComponent();
    this.DataContext = new MemberViewModel{};
}

由于第二个 new,我假设您在两个选项卡中都获得了默认值.

I assume you are getting default values in both tabs due to this second new.

这篇关于WPF 用户控件的多个实例都使用相同的 ViewModel的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆