我目前正在使用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
。因此,在ViewModel中更改MyProperty
时,视图不会更新。
我已经尝试使用UpdateSourceTrigger
属性,但它无效。此外,我没有绑定错误,转换器工作正常(我只在应用程序启动时看到一个StackPanel
。)
请注意,除非没有其他解决方案,否则我不想使用部分代码。
感谢您的帮助。
答案 0 :(得分:1)
我终于放弃并使用了部分背后的代码,现在它正常工作。
答案 1 :(得分:0)
你的<StackPanel>
是否是某个UserControl的一部分?如果没有,为什么使用DependencyProperty
?
你的实施也很不错。
让我们假设这不是自定义控件的一部分(纠正我 - 如果我错了,我会重写解决方案)
所以你有一个ViewModel,你想要连接一些属性。你真的不需要实现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;
答案 2 :(得分:0)
我认为应该使用OnPropertyChanged方法来赋予属性名称,
public bool MyProperty
{
get { return (bool) GetValue(MyPropertyProperty); }
set {
SetValue(MyPropertyProperty, value);
OnPropertyChanged("MyProperty");
}
}
https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.data.inotifypropertychanged.propertychanged