2014-10-29 106 views
0

我有一個TabViewModel至少包含一個依賴屬性CurrentViewModel。 CurrentViewModel屬性綁定到視圖TabView.xaml中的ContentControl。該TabViewModel還包含一個命令,CurrentViewModel更改爲ProductViewModel:WPF MVVM改變viewmodel調用舊viewmodel依賴屬性

​​

TabView.xaml

我實例化TabViewModel這樣的:

new TabViewModel("Producten", new ProductsViewModel()) 

的ProductsView.xaml顯示爲它應該是。在ProductsView.xaml我打電話從TabViewModel這樣的命令:

<DataGrid.InputBindings> 
      <MouseBinding 
      MouseAction="LeftDoubleClick" 
       Command="{Binding DataContext.NavigateToProductViewModelCommand, RelativeSource={RelativeSource AncestorType={x:Type views:TabView}}}"/> 
     </DataGrid.InputBindings> 

在DataGrid是空的,命令被執行,ProductView.xaml看起來像它應該是。但是當datagrid不是空的時候會發生一些奇怪的事情:

該命令被執行,當我調試時,我可以看到currentViewModel更改爲ProductViewModel。然後調用OnPropertyChanged(「CurrentViewModel」)。對於ProductsViewModel上的依賴屬性(SelectedAssetCategory)有一個set調用(value = null),這個屬性被替換並且不再退出?!

當我把CurrentViewModel = null發生同樣的事情,我只能做CurrentViewModel = new ProductsViewModel。所以我想這與更新UI有關係嗎?

在App.xaml中我定義以下的recources:

<DataTemplate DataType="{x:Type viewmodels:TabViewModel}"> 
     <views:TabView /> 
    </DataTemplate> 

    <DataTemplate DataType="{x:Type viewmodels:ProductsViewModel}"> 
     <views:ProductsView /> 
    </DataTemplate> 

    <DataTemplate DataType="{x:Type viewmodels:ProductViewModel}"> 
     <views:ProductView /> 
    </DataTemplate> 

的ProductsViewModel看起來是這樣的:

class ProductsViewModel: PageViewModel 
{ 
    private readonly MonitotingToolEntities _databaseEntities; 

    public ProductsViewModel() 
    { 
      _databaseEntities = new MonitotingToolEntities(); 

     AssetCategories = new ObservableCollection<AssetCategory>(_databaseEntities.AssetCategory.ToList()) 
     { 
      new AssetCategory() {AssetCategoryID = 0, AssetCategoryName = "Alles"} 
     }; 

     Results = new ObservableCollection<Product>(); 
    } 

    public ObservableCollection<AssetCategory> AssetCategories { get; set; } 

    private AssetCategory _selectedAssetCategory; 
    public AssetCategory SelectedAssetCategory 
    { 
     get { return _selectedAssetCategory; } 
     set 
     { 
      _selectedAssetCategory = value; //this one is called with value = null 
      OnPropertyChanged("SelectedAssetCategory"); 
      Filter(); 
     } 
    } 

    public ObservableCollection<Product> Results { get; set; } 

    public void Filter() 
    { 
     Results.Clear(); 

     List<Product> products = 
      SelectedAssetCategory.AssetCategoryID == 0 
       ? _databaseEntities.Product.ToList() 
       : SelectedAssetCategory.Product.ToList(); 

     foreach (Product product in products) 
     { 
      Results.Add(product); 
     } 
    } 
} 

ProductsView.xaml:

<UserControl x:Class="Monitoring_Tool.Views.ProductsView" 
     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" 
     xmlns:views="clr-namespace:Monitoring_Tool.Views" 
     xmlns:componentModel="clr-namespace:System.ComponentModel;assembly=WindowsBase" 
     xmlns:sys="clr-namespace:System;assembly=mscorlib" 
     xmlns:viewModels="clr-namespace:Monitoring_Tool.ViewModels" 
     mc:Ignorable="d" 
     d:DesignHeight="300" d:DesignWidth="300"> 

<UserControl.Resources> 


    <CollectionViewSource x:Key="CvsAssetCategories" Source="{Binding Path= AssetCategories}" > 
     <CollectionViewSource.SortDescriptions> 
      <componentModel:SortDescription PropertyName="AssetCategoryID"/> 
     </CollectionViewSource.SortDescriptions> 
    </CollectionViewSource> 

    <CollectionViewSource x:Key="CvsResults" Source="{Binding Path= Results}" > 
     <CollectionViewSource.GroupDescriptions> 
      <PropertyGroupDescription PropertyName="AssetCategory.AssetCategoryName" /> 
     </CollectionViewSource.GroupDescriptions> 
    </CollectionViewSource> 

    <Style TargetType="Image" x:Key="ImageDisabledStyle"> 
     <Style.Triggers> 
      <Trigger Property="IsEnabled" Value="False"> 
       <Setter Property="Opacity" Value="0.5" /> 
      </Trigger> 
     </Style.Triggers> 
    </Style> 

</UserControl.Resources> 

<Grid> 

    <Grid.RowDefinitions> 
     <RowDefinition Height="auto" /> 
     <RowDefinition Height="*" /> 
     <RowDefinition Height="auto" /> 
    </Grid.RowDefinitions> 

    <Grid Margin="0, 0, 0, 10" Grid.Row="0"> 

     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="auto"/> 
      <ColumnDefinition Width="2*"/> 
      <ColumnDefinition Width="3*"/> 
      <ColumnDefinition Width="auto"/> 
      <ColumnDefinition Width="*"/> 
      <ColumnDefinition Width="*"/> 
      <ColumnDefinition Width="auto"/> 
      <ColumnDefinition Width="auto"/> 
     </Grid.ColumnDefinitions> 

     <TextBlock Text="Asset Categorie:" Grid.Column="0" VerticalAlignment="Center" Margin="0,0,10,0"/> 

     <ComboBox Grid.Column="1" 
        ItemsSource="{Binding Source={StaticResource CvsAssetCategories}}" 
        DisplayMemberPath="AssetCategoryName" 
        SelectedItem="{Binding SelectedAssetCategory}" 
        Margin="0,0,10,0"/> 

     <TextBlock Text="Zoeken:" Grid.Column="3" VerticalAlignment="Center" Margin="0,0,10,0"/> 

     <ComboBox Grid.Column="4" 
        SelectedItem="{Binding SelectedSearchField}" 
        Margin="0,0,10,0"/> 

     <TextBox Text="{Binding Path=SearchQuery, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
       Grid.Column="5" Margin="0,0,10,0"> 
      <TextBox.InputBindings> 
       <KeyBinding Command="{Binding Path=SearchCommand}" CommandParameter="{Binding SearchQuery}" Key="Enter" /> 
      </TextBox.InputBindings> 
     </TextBox> 

     <Button Grid.Column="6" 
       Command="{Binding SearchCommand}" 
       CommandParameter="{Binding SearchQuery}" 
       Padding="5,0,5,0" Margin="0,0,10,0" > 
      <Button.Content> 
       <Image Source="/Recourses/SearchIcon.png" 
        Stretch="None" VerticalAlignment="Top" Style="{Binding Source={StaticResource ImageDisabledStyle}}"/> 
      </Button.Content> 
     </Button> 

     <Button Grid.Column="7" 
       Command="{Binding CancelSearchCommand}" 
       IsEnabled="{Binding CancelSearchEnabled}" 
       Padding="5,0,5,0"> 
      <Button.Content> 
       <Image Source="/Recourses/CancelSearchIcon.png" 
        Stretch="None" VerticalAlignment="Top" Style="{Binding Source={StaticResource ImageDisabledStyle}}"/> 
      </Button.Content> 

     </Button> 
    </Grid> 


    <DataGrid Name="DgProducts" AutoGenerateColumns="False" 
       RowHeaderWidth="0" Margin="0,0,0,10" Grid.Row="1" IsReadOnly="True" 
       SelectionMode="Single" CanUserReorderColumns="False" 
       EnableRowVirtualization="True" VirtualizingPanel.IsVirtualizingWhenGrouping="True" 
       ItemsSource="{Binding Source={StaticResource CvsResults}}" SelectedItem="{Binding SelectedProduct}"> 

     <DataGrid.CellStyle> 
      <Style TargetType="DataGridCell"> 
       <Setter Property="BorderThickness" Value="0"/> 
      </Style> 
     </DataGrid.CellStyle> 

     <DataGrid.InputBindings> 
      <MouseBinding 
      MouseAction="LeftDoubleClick" 
       Command="{Binding DataContext.NavigateToProductViewModelCommand, RelativeSource={RelativeSource AncestorType={x:Type views:TabView}}}" 
       /> 
     </DataGrid.InputBindings> 

     <DataGrid.Resources> 

      <Style TargetType="DataGridColumnHeader" x:Key="DgVerticalColumnHeader"> 
       <Setter Property="LayoutTransform"> 
        <Setter.Value> 
         <RotateTransform Angle="270" /> 
        </Setter.Value> 
       </Setter> 
      </Style> 

      <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" 
       Color="LightGray"/> 

      <SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey }" 
       Color="Black"/> 

     </DataGrid.Resources> 

     <DataGrid.GroupStyle> 
      <GroupStyle> 
       <GroupStyle.ContainerStyle> 
        <Style TargetType="GroupItem"> 
         <Setter Property="Template"> 
          <Setter.Value> 
           <ControlTemplate TargetType="GroupItem"> 
            <StackPanel> 
             <TextBlock Text="{Binding Path=Name}" Background="DarkGray" Padding="2,0,0,0"/> 
             <ItemsPresenter/> 
            </StackPanel> 
           </ControlTemplate> 
          </Setter.Value> 
         </Setter> 
        </Style> 
       </GroupStyle.ContainerStyle> 
      </GroupStyle> 
     </DataGrid.GroupStyle> 

     <DataGrid.Columns> 
      <DataGridTextColumn Binding="{Binding Path=Manager.ManagerName}" Header="Manager" /> 
      <DataGridTextColumn Binding="{Binding Path=ProductName}" Header="Product" /> 
      <DataGridTextColumn Binding="{Binding Path=MonitoringBy}" Header="Monitoring door" /> 
      <DataGridTextColumn Binding="{Binding Path=AumProduct}" Header="AUM Product (mln)" /> 
      <DataGridTextColumn Binding="{Binding Path=AumProductDate, StringFormat='{}{0:dd-MM-yyyy}'}" Header="Datum AUM Product" /> 
      <DataGridTextColumn Binding="{Binding Path=AumStrategy}" Header="AUM Strategie (mln)" /> 
      <DataGridTextColumn Binding="{Binding Path=AumStrategyDate, StringFormat='{}{0:dd-MM-yyyy}'}" Header="Datum AUM Strategie" /> 

      <DataGridTextColumn Binding="{Binding Path=Aum}" Header="AUM (mln)" /> 

      <DataGridTextColumn Binding="{Binding Path=TotalExpenseRatio}" Header="TER (bp)" /> 

      <DataGridTextColumn Binding="{Binding Path=Fee}" Header="Total Fee" /> 

    </DataGrid> 

    <Grid Grid.Row="2"> 

     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="auto" /> 
      <ColumnDefinition Width="*" /> 
      <ColumnDefinition Width="auto" /> 
      <ColumnDefinition Width="auto" /> 
     </Grid.ColumnDefinitions> 

     <TextBlock Text="{Binding Path=Results.Count, StringFormat='{}{0} Producten'}" Grid.Column="0" Margin="0,0,0,0"/> 

     <Button Grid.Column="2" 
       Content="Toevoegen" 
       Padding="5,0,5,0" Margin="0,0,10,0" 
       Command="{Binding AddProductCommand}" /> 

     <Button Grid.Column="3" 
       Content="Verwijderen" 
       Padding="5,0,5,0" 
       Command="{Binding Path=RemoveProductCommand}" 
       CommandParameter="{Binding Path=SelectedProduct}"/> 
    </Grid> 

</Grid> 

帕格eViewModel是一個抽象類:

public abstract class PageViewModel: BaseViewModel 
{ 
    private int _pageProgress; 
    public int PageProgress 
    { 
     get { return _pageProgress; } 
     set 
     { 
      _pageProgress = value; 
      OnPropertyChanged("PageProgress"); 
     } 
    } 
} 
+0

如果我們可以看到綁定'TabViewModel'和相關的'SelectedAssetCategory'屬性的XAML,最好是整個'DataGrid'的XAML,診斷可能會更容易。 'TabViewModel','PageViewModel'和UI的結構之間的關係還不清楚。 – karmasponge 2014-10-29 10:49:16

+0

@karmasponge我添加了xaml文件。 TabView是根視圖,它包含來自CurrentViewModel的視圖。 CurrentViewModel必須從PageViewModel插入 – 2014-10-29 11:22:10

+0

我相信問題是與默認的WPF'ComboBox.SelectedItem'依賴屬性的工作方式有關,但我必須確認。我看不出有什麼明顯錯誤的代碼(儘管可能值得創建一個精簡版來隔離它)。 – karmasponge 2014-10-29 19:27:15

回答

0

這是一種奇怪的,但它有事情做與collectionviewsource綁定到組合框(CvsAssetCategories)。如果我不使用collectionviewsource直接綁定到組合框,則不會調用依賴項屬性。但是,我喜歡使用collectionviewsource作爲sortdescriptor。我現在的解決方案是從依賴項屬性中對setter進行非空檢查,但我認爲它是一種討厭的方式。