多个WPF用户控件实例都使用相同的ViewModel

5
我有一个应用程序,当我点击一个按钮时,会加载一个带有UserControl的新TabItem。这个看起来是工作正常的,但是...当我再次点击“添加”按钮时,会再添加一个TabItem,并且会显示一个新的UserControl实例。问题来了。
当我在tab1中添加一些数据并切换到tab2时,我也能够在那里看到输入的数据。这怎么可能?每个UserControl都使用一个新的ViewModel,所以为什么tab1和tab2上的两个用户控件都显示相同的数据呢?
可能是某些愚蠢的问题,但我找不到原因...
结构如下:MainWindow会加载一个只有TabControl的UserControl。在菜单中点击添加按钮后,会添加一个新的TabItem,其中包含一个新的UserControl。
这里有一些代码。
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有一个数据属性(DP),用于保存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); }
}

要加载到TabItem上的UserControl,需要使用MemberControl.cs

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 作为新的 TabItemTabControl 的命令:

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

在某个地方,我在绑定方面做错了什么,但正如所说,我找不到它。

感谢任何帮助。

1个回答

4

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

一次是当您将MemberViewModel添加到选项卡集合中时:

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

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

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

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

我假设你在两个选项卡中都得到了默认值,是因为这里有第二个 "new"。

的确,我有一个想法,但那不正确,那么该怎么做呢?如果我在MemberControl中省略这一行“this.DataContext = new MemberViewModel{};”,我认为MemberControl与ViewModel之间就没有绑定了,或者我错了吗?感谢您确认我的猜想.. :) - PitAttack76
你可以省略它。你的 DataTemplate 已经为你完成了它。一个模板会将 XAML "视图" 包装在一个数据对象周围,而对象是被模板化 XAML 的 DataContext。 - GazTheDestroyer
1
刚刚一直在测试这个,看起来好像可以工作了 :) 我确信之前试过,但是没有成功,但现在好像可以了。我尝试了几种方法,可能那就是问题所在...会继续测试并告诉你结果的..谢谢! - PitAttack76

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接