2015-01-16 2 views
0

Привет, извините за длинный пост. Надеюсь, никто не задал тот же вопрос. Если это так, я прошу ваших оправданий. У меня проблема с добавлением TabItem динамически, из другого контента TabItem, witch is UserControl, используя подход MVVM. MainWindow имеет класс ViewModel переплетены под названием TabsMainViewModel:MVVM WPF Добавление TabItem из другого содержимого TabItem

<Window x:Name="Main" x:Class="Interface_test.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:vm="clr-namespace:Interface_test" 
     xmlns:uc="clr-namespace:Interface_test.Customers" 
     Title="MainWindow" Height="850" Width="825" WindowStartupLocation="CenterScreen" WindowState="Maximized"> 
    <Window.DataContext> 
     <vm:TabsMainViewModel /> 
    </Window.DataContext> 
    <Window.Resources> 
    <DataTemplate x:Key="TabItemTemplate"> 
     <DockPanel> 
      <Button Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" 
        Background="Transparent" 
        Name="btnDelete" 
        DockPanel.Dock="Right" 
        Margin="5,0,0,0" 
        Padding="0" 
        Command="{Binding RemoveItemCommand}"> 
       <Image Height="11" Width="11" Source="Images/closeButton.png"/> 
      </Button> 
      <TextBlock Text="{Binding Header}" /> 
     </DockPanel> 
    </DataTemplate> 
    <DataTemplate x:Key="TabItemContent" > 
     <UserControl Content="{Binding TabContent}"/> 
    </DataTemplate> 
    <Style TargetType="TabItem"> 
     <Setter Property="IsSelected" 
       Value="{Binding IsSelected, Mode=TwoWay}"/> 
    </Style> 
</Window.Resources> 
<TabControl ItemTemplate="{StaticResource TabItemTemplate}" 
       ContentTemplate="{StaticResource TabItemContent}" 
       ItemsSource="{Binding Tabs}" 
       HorizontalAlignment="Stretch" 
       VerticalAlignment="Stretch" 
       VerticalContentAlignment="Stretch" 
       HorizontalContentAlignment="Stretch" 
       Name="tcMDI" 
       Visibility="Visible" 
       ScrollViewer.HorizontalScrollBarVisibility="Auto" 
       ScrollViewer.VerticalScrollBarVisibility="Auto" > 

В TabsMainViewModel У меня есть один ObservableCollection из пользовательского класса под названием TabViewModel.

public class TabsMainViewModel 
    { 
     int tabCounter; 
     private Dictionary<string, string> _openedTabs = new Dictionary<string, string>(); 
     public TabsMainViewModel() 
     { 
      this.Tabs=new ObservableCollection<TabViewModel>(); 
      //this.AddItem(null); 
     } 
     public ObservableCollection<TabViewModel> Tabs 
     { 
      get; 
      private set; 
     } 
     public ICommand CustomerSearch 
     { 
      get 
      { 
       CustomerSearch f = new CustomerSearch() { UniqueTabName = "NewTab1", Title = "Customer Search" }; 
       return new DelegateCommand(delegate { this.AddItem(f); }); 
      } 

     } 
     public ICommand Customer 
     { 
      get 
      { 
       Customer f = new Customer() { UniqueTabName = "NewTab2", Title = "Customer" }; 
       return new DelegateCommand(delegate { this.AddItem(f); }); 
      } 

     } 
     public ICommand EmployerSearch 
     { 
      get 
      { 
       CustomerSearch f = new CustomerSearch() { UniqueTabName = "NewTab3", Title = "Employer Search" }; 
       return new DelegateCommand(delegate { this.AddItem(f); }); 
      } 
     } 
     public ICommand Employer 
     { 
      get 
      { 
       Customer f = new Customer() { UniqueTabName = "NewTab4", Title = "Employer" }; 
       return new DelegateCommand(delegate { this.AddItem(f); }); 
      } 

     } 
     public void AddItem(ITabContent userControl) 
     { 

      if (_openedTabs.ContainsKey(userControl.UniqueTabName)) 
      { 
       foreach (TabViewModel tvm in Tabs) 
       { 
        if (userControl.UniqueTabName == tvm.TabContent.UniqueTabName) 
        { 
         tvm.IsSelected = true; 
         break; 
        } 
       } 
      } 
      else 
      { 
       TabViewModel tabItem = new TabViewModel(this) { TabContent = userControl }; 
       tabItem.TabContent.Title += " " + tabCounter; 
       tabItem.IsSelected = true; 
       Tabs.Add(tabItem); 
       _openedTabs.Add(tabItem.TabContent.UniqueTabName, tabItem.TabContent.Title); 
       tabCounter++; 
      } 

     } 
     public void RemoveItem(TabViewModel tabItem) 
     { 
      this.Tabs.Remove(tabItem); 
      _openedTabs.Remove(tabItem.TabContent.UniqueTabName); 
      tabItem.Dispose(); 

     } 
    } 
} 

TabViewModel Класс, у меня есть:

public class TabViewModel:ObservableObject,IDisposable 
    { 
     private bool _isSelected; 
     private ITabContent _tabContent; 
     private readonly TabsMainViewModel tabsMainViewModel; 

     public TabViewModel(TabsMainViewModel tabsMainViewModel) 
     { 
      this.tabsMainViewModel = tabsMainViewModel; 
      this.tabsMainViewModel.Tabs.CollectionChanged += this.Tabs_CollectionChanged; 


      this.RemoveItemCommand = new DelegateCommand(
       delegate 
       { 
        this.tabsMainViewModel.RemoveItem(this); 
       }, 
       delegate 
       { 
        return this.tabsMainViewModel.Tabs.Count > 1; 
       } 
       ); 
     } 
     public void Dispose() 
     { 
      this.tabsMainViewModel.Tabs.CollectionChanged -= this.Tabs_CollectionChanged; 
     } 
     private void Tabs_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 
     { 
      this.RemoveItemCommand.RaiseCanExecuteChanged(); 
     } 

     public DelegateCommand RemoveItemCommand { get; set; } 

     public ITabContent TabContent 
     { 
      get { return _tabContent;} 
      set 
      { 
       _tabContent = value; 
       _tabContent.Parent = this; 
       Header = value.Title; 
      } 
     } 
     public String Header 
     { 
      get; 
      private set; 
     } 
     public bool IsSelected 
     { 
      get { return this._isSelected; } 
      set 
      { 
       if (this._isSelected != value) 
       { 
        this._isSelected = value; 
        RaisePropertyChangedEvent("IsSelected"); 
       } 
      } 
     } 
    } 
} 

В TabContent собственности я поставил UserControl, который появляется в содержимое TabItem «s. Мой вопрос: как я могу поместить кнопку в этот usercontrol CustomerSearch, и эту кнопку связывать что-то вроде ICommand или DelegateCommand (например, в его CustomerSearchViewModel), который может выполнять функцию AddItem в TabsMainViewModel?

При необходимости я могу разместить и ObservableObject и DelegateCommand классы и ITabContent интерфейс. Заранее спасибо

+0

Пожалуйста, никогда не реализовать 'Dispose()' метод, как вы делали это для класса 'TabViewModel'. Этот метод может быть вызван сборщиком мусора недетерминированным способом, что означает - вы не можете знать, когда, сколько раз и по какому потоку он будет вызван. – dymanoid

+0

Спасибо за подсказку. Я буду помнить об этом. Любые предложения по поводу вопроса, который я задал? :) –

ответ

0

У меня есть проблемы с моей проблемой. Я отправлю решение для двойной проверки, и если у кого-то будет такая же проблема. Таким образом, решение таково:

Добавить класс, который является моделью CustomerSearch под названием CustomerSearchViewModel. В этом классе вы добавить функцию делегата и событие, которое зарегистрировано в TabsMainViewModel:

namespace Interface_test.Customers 
{ 
    public delegate void OpenNewTab(ITabContent uc); 
    class CustomerSearchViewModel 
    { 
     public static event OpenNewTab AddNewCustomerTab = delegate { }; 
     public CustomerSearchViewModel() 
     { 

     } 
     public ICommand ShowCustomer 
     { 
      get 
      { 
       Customer f = new Customer() { UniqueTabName = "NewTab12", Title = "Customer from search" }; 
       return new DelegateCommand(delegate {AddNewCustomerTab(f); }); 
      } 

     } 

    } 
} 

В главном ViewModel TabsMainViewModel где я создаю экземпляр UserControl, я зарегистрировать событие:

public ICommand CustomerSearch 
     { 
      get 
      { 
       CustomerSearch f = new CustomerSearch() { UniqueTabName = "NewTab1", Title = "Customer Search" }; 
       CustomerSearchViewModel.AddNewCustomerTab += AddItem; 
       return new DelegateCommand(delegate { this.AddItem(f); }); 
      } 

     } 

Я не знаю, подходит ли это, но это сработало для меня. Если у кого-то есть лучшее решение, не стесняйтесь поделиться им.

С наилучшими пожеланиями,

Джулиан

Смежные вопросы