2013-10-26 27 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

相关问题