2013-10-26 32 views
0

第一:我是MVVM和WPF的新手。Wpf MVVM - 選項卡式界面不能按預期工作

我想用選項卡式用戶界面創建一個小應用程序。用戶可以使用應打開新TabItem的按鈕來創建產品和存儲位置。

我的視圖代碼如下所示:

<TabControl ItemsSource="{Binding Workspaces}" 
     IsSynchronizedWithCurrentItem="True" 
     Margin="3" 
     DockPanel.Dock="Top"> 
    <TabControl.ItemTemplate> 
     <DataTemplate> 
      <Label Content="{Binding DisplayName}" /> 
     </DataTemplate> 
    </TabControl.ItemTemplate> 
</TabControl> 

和視圖模型是這樣的:

ObservableCollection<WorkspaceViewModel> _workspaces; 
    public ObservableCollection<WorkspaceViewModel> Workspaces 
    { 
     get 
     { 
      if (_workspaces == null) 
      { 
       _workspaces = new ObservableCollection<WorkspaceViewModel>(); 
      } 
      return _workspaces; 
     } 
     set 
     { 
      _workspaces = value; 

     } 
    } 
public void AddProduct(object obj) 
    { 
     Workspaces.Add(new ProductViewModel()); 
    } 

其他各種按鈕添加不同的ViewModels到工作區集合。

我已經定義了多個數據模板(每個ViewModel一個)。這裏是一個:

<DataTemplate DataType="{x:Type vm:ProductViewModel}"> 
    <vw:ProductView /> 
</DataTemplate> 

的WorkspaceViewModel是這樣的:

namespace Inventory.Desktop.ViewModels 
{ 
public abstract class WorkspaceViewModel : INotifyPropertyChanged 
{ 
    #region Events and EventHandlers 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected void NotifyPropertyChanged(string propertyName) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    #endregion 
} 
} 

和例如ProductViewModel

namespace Inventory.Desktop.ViewModels 
{ 
public class ProductViewModel: WorkspaceViewModel 
{ 
    private Product _product; 
    private string _displayName; 


    public string DisplayName 
    { 
     get 
     { 
      if (String.IsNullOrEmpty(_displayName)) 
      { 
       return "Neues Produkt"; 
      } else 
      { 
       return _displayName; 
      } 
     } 
     set 
     { 
      _displayName = value; 
      NotifyPropertyChanged("DisplayName"); 
     } 
    } 


    #region Public Properties 

    public Product Product 
    { 
     get 
     { 
      return _product; 
     } 
     set 
     { 
      _product = value; 
      NotifyPropertyChanged("Product"); 
     } 
    } 

    public string Title 
    { 
     get 
     { 
      return _product.Title; 
     } 
     set 
     { 
      _product.Title = value; 
      NotifyPropertyChanged("Title"); 
     } 
    } 

    public string ScanCode 
    { 
     get 
     { 
      return _product.ScanCode; 
     } 
     set 
     { 
      _product.ScanCode = value; 
      NotifyPropertyChanged("ScanCode"); 
     } 
    } 

    public string Manufacturer 
    { 
     get 
     { 
      return _product.Manufacturer; 
     } 
     set 
     { 
      _product.Manufacturer = value; 
      NotifyPropertyChanged("Manufacturer"); 
     } 
    } 

    public string ManufacturerNumber 
    { 
     get 
     { 
      return _product.ManufacturerNumber; 
     } 
     set 
     { 
      _product.ManufacturerNumber = value; 
      NotifyPropertyChanged("ManufacturerNumber"); 
     } 
    } 

    public string Description 
    { 
     get 
     { 
      return _product.Description; 
     } 
     set 
     { 
      _product.Description = value; 
      NotifyPropertyChanged("Description"); 
     } 
    } 

    #endregion 

    #region Commands 

    private ICommand _saveCommand; 

    public ICommand SaveCommand 
    { 
     get 
     { 
      return _saveCommand; 
     } 
     set 
     { 
      _saveCommand = value; 
     } 
    } 

    #endregion 

    #region Command Executions 

    public void Save(object obj) 
    { 

     using (var db = new InvContext()) 
     { 
      db.Products.Attach(Product); 
      db.Entry(Product).State = Product.ProductId == 0 ? 
       EntityState.Added : EntityState.Modified; 
      db.SaveChanges(); 
     } 

     MessageBox.Show("Product saved: " + Product.Title); 
    } 

    #endregion 

    #region Constructors 

    public ProductViewModel() 
    { 
     if (_product == null) 
     { 
      _product = new Product(); 
     } 

     SaveCommand = new RelayCommand(new Action<object>(Save)); 
    } 

    #endregion 


} 
} 

這裏ProductView.xaml觀點:

<UserControl x:Class="Inventory.Desktop.Views.ProductView" 
     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="400" d:DesignWidth="450"> 
<DockPanel> 
    <StackPanel DockPanel.Dock="Top" Orientation="Horizontal" FlowDirection="RightToLeft"> 
     <Button Name="SaveProductButton" Command="{Binding SaveCommand}" Content="Speichern" Margin="3" BorderThickness="0"> 
     </Button> 
    </StackPanel> 
    <StackPanel DockPanel.Dock="Top" VerticalAlignment="Stretch"> 
     <Label Content="Scan Code" /> 
     <TextBox Text="{Binding Path=ScanCode}" HorizontalAlignment="Stretch" Margin="3" Padding="3" Height="50" TextAlignment="Right"> 
      <TextBox.Background> 
       <ImageBrush ImageSource="..\Images\Barcode32.png" AlignmentX="Left" Stretch="None" /> 
      </TextBox.Background> 
     </TextBox> 
     <Label Content="Bezeichnung" /> 
     <TextBox Text="{Binding Path=Title, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Stretch" Margin="3" /> 
     <Label Content="Hersteller" /> 
     <TextBox Text="{Binding Path=Manufacturer, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Stretch" Margin="3" /> 
     <Label Content="Hersteller Nummer" /> 
     <TextBox Text="{Binding Path=ManufacturerNumber, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Stretch" Margin="3" /> 
     <Label Content="Beschreibung/Information" /> 
     <TextBox Text="{Binding Path=Description, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Stretch" Margin="3" /> 
    </StackPanel> 

</DockPanel> 
</UserControl> 

和這裏的代碼-beh IND ProductView.xaml.cs

namespace Inventory.Desktop.Views 
{ 
/// <summary> 
/// Interaktionslogik für ProductView.xaml 
/// </summary> 
public partial class ProductView : UserControl 
{ 

    ProductViewModel _productModel = new ProductViewModel(); 

    public ProductView() 
    { 
     InitializeComponent(); 
     base.DataContext = _productModel; 
    } 
} 
} 

什麼是目前的工作:

  • 當我點擊一個按鈕,我得到了一個新的TabItem顯示正確的觀點和所有的命令正常工作。

什麼是不工作:

  • 當我打開的TabItem,輸入一些信息,然後我打開一個不同的視圖模型的另一個的TabItem,切換焦點到新的TabItem,然後回原來的oen,那麼所有輸入的信息都消失了(對象爲null)。

  • 當我打開一個TabItem,輸入一些信息,然後用相同的ViewModel打開另一個TabItem,然後兩個TabItems顯示相同的信息。

  • 當我添加一個新的TabItem時,它不會得到焦點。

我完全失去了,我希望你能告訴我我做錯了什麼。

最佳

斯特凡

+0

好像問題出在你的WorkspaceViewModel,你能發佈一些資訊? –

+0

Hi Mujahid。我編輯我的問題,幷包括模型 – Stefan

+0

嘗試使用UpdateSourceTrigger = PropertyChanged在您的問題的文本框 –

回答

1

對您的視圖模型的屬性來存儲參考電流/所選標籤

public WorkspaceViewModel SelectedTab 
{ 
    get { return _selectedTab; } 
    set 
    { 
     _selectedTab = value; 
     RaisePropertyChanged(() => SelectedTab); 
    } 
} 

並結合這對TabControl的SelectedItem財產。

<TabControl ItemsSource="{Binding Workspaces}" 
     SelectedItem="{Binding SelectedTab, Mode=TwoWay}" 
     Margin="3" 
     DockPanel.Dock="Top"> 
    <TabControl.ItemTemplate> 
     <DataTemplate> 
      <Label Content="{Binding DisplayName}" /> 
     </DataTemplate> 
    </TabControl.ItemTemplate> 
</TabControl> 

最後,要更新SelectedTab財產每當你添加新的選項卡。修改您AddProduct這樣的:約WorkspaceViewModel

public void AddProduct(object obj) 
    { 
     var workspace = new ProductViewModel(); 
     Workspaces.Add(workspace); 
     SelectedTab = workspace; 
    } 
+0

謝謝。這解決了我的一個問題,我現在在添加新選項卡時獲得焦點。 – Stefan

+0

@Stefan是否嘗試刪除'IsSynchronizedWithCurrentItem =「True」'並查看是否可以解決其他兩個問題? – sthotakura

相關問題