[英]Binding of control visibility to ViewModel property doesn't work
我正在將相當大的WPF應用程序從三層轉換為MVVM,並且正在學習MVVM。 到目前為止,我還沒有深入研究Bindings(等)的細節,所以請耐心等待。
我試圖將多個控件的System.Windows.Visibility綁定到ViewModel的公共屬性(“狀態”)。 加載父TabItem時,將根據需要讀取和處理State屬性。 但是,當對該屬性進行后續更改時,它們似乎被忽略了。 我已經(重新-重新-)檢查了綁定,調試了轉換器,等等,這讓我發瘋了。
視圖模型:
public class MarketingListViewModel: IDisposable, INotifyPropertyChanged
{
private UiState state;
public event PropertyChangedEventHandler PropertyChanged;
public UiState State
{
get { return state; }
set
{
if (state != value)
{
state = value;
NotifyPropertyChanged("State");
}
}
}
public MarketingListViewModel()
{
State = UiState.View;
}
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
視圖:
<UserControl 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:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
mc:Ignorable="d" x:Class="WpfCrm.tabListManager" xmlns:DPH="clr-namespace:DPH" >
<UserControl.Resources>
<DPH:MarketingListViewModel x:Key="listVM" />
<!-- Note that the above line is giving me an "Object reference not set to an instance of an object" error -->
</UserControl.Resources>
<Grid x:Name="gridMain" DataContext="{StaticResource listVM}" >
<Border Grid.Row="0" Grid.Column="1" Margin="10"
Style="{StaticResource WidgetStyle}" >
<Grid x:Name="gridListManagement" >
<Label x:Name="labelManageLists" Content="Manage Lists" MouseDown="labelManageLists_MouseDown"
Style="{StaticResource WidgetTitleStyle}"
Grid.Row="0" Grid.Column="0" />
<StackPanel Grid.Row="0" Grid.Column="2" Orientation="Horizontal" HorizontalAlignment="Right" >
<Label x:Name="llNewList" Content="new" MouseDown="llNewList_MouseDown"
Style="{StaticResource LinkLabelStyle}"
HorizontalAlignment="Right" />
<Label x:Name="llCloseManageLists" Content="close" MouseDown="llCloseManageLists_MouseDown"
Style="{StaticResource LinkLabelStyle}"
HorizontalAlignment="Right" />
</StackPanel>
<Label x:Name="labelListName" Content="Name" Grid.Row="1" Grid.Column="0" />
<Grid Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" HorizontalAlignment="Stretch" >
<ComboBox x:Name="cbLists" SelectedIndex="-1" SelectionChanged="cbLists_SelectionChanged" IsReadOnly="True"
ItemsSource="{Binding Path=AllMarketingLists}"
DisplayMemberPath="Name"
SelectedValuePath="Id"
Visibility="{Binding Path=State, Converter={StaticResource ViewStateToVisibilityConverter} }"/>
<TextBox x:Name="tbListName"
Text="{Binding Path=OList.Name}"
Visibility="{Binding Path=State, Converter={StaticResource EditStateToVisibilityConverter} }"/>
</Grid>
<Label x:Name="labelListDescription" Content="Description" Grid.Row="2" Grid.Column="0" />
<Grid Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" >
<TextBlock x:Name="textblockListDescription" TextWrapping="Wrap"
Text="{Binding Path=OList.Notes}"
Visibility="{Binding Path=State, Converter={StaticResource ViewStateToVisibilityConverter} }"
Grid.ColumnSpan="2" />
<TextBox x:Name="tbListDescription" TextWrapping="Wrap"
Text="{Binding Path=OList.Notes}"
Visibility="{Binding Path=State, Converter={StaticResource EditStateToVisibilityConverter} }"
Grid.ColumnSpan="2" />
</Grid>
<StackPanel Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="3" HorizontalAlignment="Right" Orientation="Horizontal" >
<Button x:Name="buttonEditList" Content="Edit" Click="buttonEditList_Click"
Visibility="{Binding Path=State, Converter={StaticResource ViewStateToVisibilityConverter} }"
Width="60" Margin="3" />
<Button x:Name="buttonSaveList" Content="Save" Click="buttonSaveList_Click"
Visibility="{Binding Path=State, Converter={StaticResource EditStateToVisibilityConverter} }"
Width="60" Margin="3" />
<Button x:Name="buttonCancel" Content="Cancel" Click="buttonCancel_Click"
Visibility="{Binding Path=State, Converter={StaticResource EditStateToVisibilityConverter} }"
Width="60" Margin="3" />
</StackPanel>
</Grid>
</Border>
</Grid>
后面的代碼有幾種方法,例如:
private void buttonEditList_Click(object sender, RoutedEventArgs e)
{
listVM.State = UiState.Edit;
}
有人對州變更后控件為什么不更新其可見性有任何想法嗎?
謝謝,
DPH
編輯-轉換器:
[ValueConversion(typeof(WpfCrm.UiState), typeof(System.Windows.Visibility))]
public class EditStateToVisibilityConverter: IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
UiState state = (UiState)value;
if (state == UiState.View) return Visibility.Collapsed;
else return Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
[ValueConversion(typeof(WpfCrm.UiState), typeof(System.Windows.Visibility))]
public class ViewStateToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
UiState state = (UiState)value;
if (state == UiState.View) return Visibility.Visible;
else return Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
您似乎使用了視圖模型的兩個不同實例,其中一個在XAML中聲明並使用過。
<UserControl.Resources>
<DPH:MarketingListViewModel x:Key="listVM" />
</UserControl.Resources>
<Grid DataContext="{StaticResource listVM}" >
和一個在代碼后面(來自注釋):
listVM = new MarketingListViewModel();
您當然應該只使用一個。 因此,將聲明后的代碼更改為
listVM = (MarketingListViewModel)Resources["listVM"];
好,有一個錯誤。 您將listVM聲明為
var listVM = new MarketingListViewModel();
但這不是XAML中的listVM。 在XAML中,您創建了MarketingListViewModel的另一個實例。 因此,當您嘗試更改在代碼中聲明的listVM時,什么也不會發生,因為此對象不是Grid的DataContext。
在您的Click處理程序中,您必須編寫以下內容:
private void buttonEditList_Click(object sender, RoutedEventArgs e)
{
var _listVM = (MarketingListViewModel)FindResource("listVM");
_listVM.State = UiState.Edit;
}
或用以下代碼替換代碼中的listVM聲明:
listVM = (MarketingListViewModel)FindResource("listVM");
然后,您無需更改事件處理程序。
希望能幫助到你。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.