我有一個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");
}
}
}
如果我們可以看到綁定'TabViewModel'和相關的'SelectedAssetCategory'屬性的XAML,最好是整個'DataGrid'的XAML,診斷可能會更容易。 'TabViewModel','PageViewModel'和UI的結構之間的關係還不清楚。 – karmasponge 2014-10-29 10:49:16
@karmasponge我添加了xaml文件。 TabView是根視圖,它包含來自CurrentViewModel的視圖。 CurrentViewModel必須從PageViewModel插入 – 2014-10-29 11:22:10
我相信問題是與默認的WPF'ComboBox.SelectedItem'依賴屬性的工作方式有關,但我必須確認。我看不出有什麼明顯錯誤的代碼(儘管可能值得創建一個精簡版來隔離它)。 – karmasponge 2014-10-29 19:27:15