当依赖项属性更改时,不会更新StackPanel可见性

时间:2014-10-28 19:48:55

标签: c# xaml mvvm win-universal-app

我目前正在使用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。)

请注意,除非没有其他解决方案,否则我不想使用部分代码。

感谢您的帮助。

3 个答案:

答案 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

相关问题