Multiple instances of a wpf user control all use t

2019-06-27 04:45发布

问题:

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 usercontrols on tab1 and tab2 show the same data. It will probably be something stupid, but I can't find it...

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..

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

Here's some code.

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 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); }
    }

The usercontrol which gets loaded on the tabitem, MemberControl.cs

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

The 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;
    }
etc...

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();
    }

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

Thx for any help.

回答1:

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

Once when you add the MemberViewModel to your tab collection:

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

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

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

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

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