相关性属性更改时,StackPanel可见性未更新
本文关键字:StackPanel 可见性 更新 属性 相关性 | 更新日期: 2023-09-27 18:28:14
我目前正在用MVVM(而不是MVVM Light)在C#/XAML中开发一个通用应用程序,但我在XAML部分遇到了问题。
当ViewModel中的依赖项属性发生更改时,我希望显示一个或另一个StackPanel
。我认为代码不言自明。
<StackPanel Visibility="{Binding MyProperty, Converter={StaticResource BooleanToVisibilityConverter}}">
<!-- Some content -->
</StackPanel>
<StackPanel Visibility="{Binding MyProperty, Converter={StaticResource InvertBooleanToVisibilityConverter}}">
<!-- Some another content -->
</StackPanel>
这是依赖属性的定义。
public static readonly DependencyProperty MyPropertyProperty = DependencyProperty.Register(
"MyProperty",
typeof (bool),
typeof (MyViewModel),
new PropertyMetadata(true));
public bool MyProperty
{
get { return (bool) GetValue(MyPropertyProperty); }
set { SetValue(MyPropertyProperty, value); OnPropertyChanged(); // Implemented by ReSharper }
}
我想你已经知道MyProperty
是一个布尔值,我通过转换器将其转换为Visibility
。因此,当MyProperty
在ViewModel中发生更改时,视图不会更新。
我已经尝试使用UpdateSourceTrigger
属性,但它不起作用。此外,我没有绑定错误,转换器工作正常(我在应用程序启动时只看到一个StackPanel
)。
请记住,除非没有其他解决方案,否则我不想使用代码隐藏部分。
谢谢你的帮助。
我最终放弃了,使用了代码隐藏部分,现在它工作得很好。
您的<StackPanel>
是某些UserControl的一部分吗?如果没有,为什么要使用DependencyProperty
?
您的实现也相当糟糕。
让我们假设一下,这不是自定义控制的一部分(纠正我——如果我错了,我会重写解决方案)
所以你有一个ViewModel,你想把一些Properties连接到它上。你真的不需要实现DependencyProperty来做你想做的事情,但我会通过你的方式来实现它来娱乐你。
这是一个具有1(一)属性的示例ViewModel
using Windows.UI.Xaml;
using System.ComponentModel;
// very simple view model
class MyViewModel : DependencyObject, INotifyPropertyChanged
{
// implement INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
// register
public static DependencyProperty FooterTitleProperty = DependencyProperty.Register("FooterTitle", typeof(string), typeof(MyViewModel),
new PropertyMetadata(string.Empty, OnFooterTitlePropertyChanged));
// the actual property
public string FooterTitle
{
get { return (string) GetValue(FooterTitleProperty); }
set
{
SetValue(FooterTitleProperty, value);
}
}
// this will fire when the property gets change
// it will call the OnPropertyChanged to notify the UI element to update its layout
private static void OnFooterTitlePropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
MyViewModel mvm = dependencyObject as MyViewModel;
mvm.OnPropertyChanged("FooterTitle");
}
}
为了测试代码,我们将制作一个非常简单的XAML表单
<Grid x:Name="ContentPanel">
<StackPanel>
<TextBlock x:Name="tb" Text="{Binding FooterTitle}" FontSize="48"></TextBlock>
<Button Content="Test Property" Click="Button_Click_1"></Button>
</StackPanel>
</Grid>
当您点击按钮时,我们将更改文本框的文本
public sealed partial class MainPage : Page
{
// create the view model
MyViewModel vm = new MyViewModel();
public MainPage()
{
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Required;
// set the text we initial want to display
vm.FooterTitle = "default text";
// set the DataContext of the textbox to the ViewModel
tb.DataContext = vm;
}
// after the button is click we change the TextBox's Text
private void Button_Click_1(object sender, RoutedEventArgs e)
{
// change the text
vm.FooterTitle = "Test Property Has Changed.";
// what happens is the Setter of the Property is called first
// after that happens it launches the `OnFooterTitlePropertyChanged` event
// that we hook up with the Register function.
// `OnFooterTitlePropertyChanged` launches the INotifyPropertyChanged event
// then finally the TextBox will updates it's layout
}
}
在这一点上,你可以猜测你真的不需要DependencyProperty,并说为什么我不能在Setter中启动INotifyPropertyChanged?你可以,而且这可能是你更喜欢的方法。
如果所有这些都是UserControl的一部分,那么我可以看到使用DependencyProperty,然后在OnFooterTitlePropertyChanged
事件中,您可以设置
name_of_textbox.Text = FooterTitle;
我认为应该使用OnPropertyChanged方法来指定属性名称,如下所示;
public bool MyProperty
{
get { return (bool) GetValue(MyPropertyProperty); }
set {
SetValue(MyPropertyProperty, value);
OnPropertyChanged("MyProperty");
}
}
https://learn.microsoft.com/en-us/uwp/api/windows.ui.xaml.data.inotifypropertychanged.propertychanged