【问题标题】:WPF: Change DataContext if Null?WPF:如果为 Null,则更改 DataContext?
【发布时间】:2014-12-09 20:02:17
【问题描述】:

我有一个视图,我想为其分配一个“备份”视图模型。本质上,如果“Generic”为空,我想将 DataContext 设置为“GenericFactory”。 “GenericFactory”能够创建“Generic”视图模型的实例。创建后,视图模型被分配给适当的属性并触发 PropertyChanged 事件,但是鉴于下面的代码,我曾经绑定的唯一 DataContext 是“GenericFactory”。谁能解释和/或提供替代解决方案?

XAML

<Page x:Class="GenericProject.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:vw="clr-namespace:GenericProject.View">
    <StackPanel>
        <!--Additional markup-->
        <vw:GenericView>
            <vw:GenericView.Style>
                <Style TargetType="{x:Type vw:GenericView}">
                    <Setter Property="DataContext" Value="{Binding Generic}" />
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding Generic}" Value="{x:Null}">
                            <Setter Property="DataContext" Value="{Binding GenericFactory}" />
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </vw:GenericView.Style>
        </vw:GenericView>
    </StackPanel>
</Page>

视图模型

public class MainPageViewModel : ViewModelBase
{
    public GenericViewModel Generic
    {
        get { return _generic; }
        private set
        {
            if (_generic != value)
            {
                _generic = value;
                base.OnPropertyChanged("Generic");
            } 
        }
    }

    public GenericFactoryViewModel GenericFactory { get; private set; }

    private void OnGenericFactoryCreatedGeneric(object sender, CreatedGenericEventArgs e)
    {
        Generic = e.Generic;
    }

    public MainPageViewModel()
    {
        GenericFactory = new GenericFactoryViewModel();
        GenericFactory.CreatedGeneric += OnGenericFactoryCreatedGeneric;
    }
}

谢谢 - 井架

【问题讨论】:

  • @ChrisW。我的印象是 TargetNullValue 不能设置为绑定?
  • 啊废话,不专心地快速阅读 SO 问题是我需要改掉的坏习惯。不管你是对的,你需要在它上面扔一个转换器,像this 这样的东西看起来很正常。对此感到抱歉。
  • 我认为您正在寻找的是 BindingPriority here 是 MSDN 链接,其中包含有关该主题的更多信息。 HTH
  • @ChrisW。感谢您提供额外的反馈,我相信转换器会起作用,但我发现自己更喜欢使用 BindingPriority 建议。

标签: c# wpf xaml mvvm


【解决方案1】:

感谢 XAMIMAX 的评论,我能够使用 PriorityBinding 找到解决方案。

XAML

<Page x:Class="GenericProject.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="clr-namespace:GenericProject"
      xmlns:vw="clr-namespace:GenericProject.View">
    <Page.Resources>
        <local:NullToDependencyPropertyUnsetConverter x:Key="NullToDependencyPropertyUnsetConverter" />
    </Page.Resources>
    <StackPanel>
        <!--Additional markup-->
        <vw:GenericView>
            <vw:GenericView.DataContext>
                <PriorityBinding>
                    <Binding Path="Generic" Converter="{StaticResource NullToDependencyPropertyUnsetConverter}" />
                    <Binding Path="GenericFactory" />
                </PriorityBinding>
            </vw:GenericView.DataContext>
        </vw:GenericView>
    </StackPanel>
</Page>

转换器

public class NullToDependencyPropertyUnsetConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value ?? DependencyProperty.UnsetValue;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

【讨论】:

    【解决方案2】:

    我不知道你的工厂是如何工作的,所以这可能不是工作代码,但你应该在视图模型中处理这个逻辑,你的视图应该只设置数据上下文。

    public GenericViewModel Generic
        {
            get 
            { 
                if(_generic == null)
                {
                    GenericFactory.Create();
                }
                return _generic;
            }
            private set
            {
                if (_generic != value)
                {
                    _generic = value;
                    base.OnPropertyChanged("Generic");
                }
            }
        }
    

    这将为 Generic 返回 null,但是当调用 OnGenericFactoryCreatedGeneric 时,它将设置 Generic,然后导致绑定更新到新创建的视图模型。

    如果您的工厂有一个返回 ViewModel 的同步创建,那会更好,因为 Generic 永远不会返回 null。 _generic = GenericFactory.Create();

    【讨论】:

    • 这适用于更简单的 GenericFactory 实现,在我的例子中,GenericFactory 是一个 ViewModel,它本身包含一个命令,并且需要视图提供的 CommandParameter 来构建 GenericViewModel。跨度>
    猜你喜欢
    • 2011-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-25
    • 2020-02-01
    • 1970-01-01
    • 2012-01-16
    • 1970-01-01
    相关资源
    最近更新 更多