WPF可扩展控件在用户交互后忽略数据绑定

3

我有一个WPF应用程序,其中包含一个可展开控件。我希望根据我的视图模型中的枚举值更改IsExpanded属性,即我希望基于此枚举属性打开或关闭可展开控件。我在xaml中使用数据触发器来根据我的枚举支持属性的值更新IsExpanded属性。

<Expander Header="Information and Procedures"
                              BorderThickness="0"
                              Margin="5">
                        <Expander.Style>
                            <Style TargetType="{x:Type Expander}" BasedOn="{StaticResource MetroExpander}">
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding DataContext.Item.Match, RelativeSource={RelativeSource AncestorType={x:Type UserControl}, Mode=FindAncestor}, Mode=TwoWay}" 
                                                 Value="{x:Static enum:Match.Multiple}">
                                        <Setter Property="IsExpanded" Value="False"/>
                                    </DataTrigger>
                                    <DataTrigger Binding="{Binding DataContext.Item.Match, RelativeSource={RelativeSource AncestorType={x:Type UserControl}, Mode=FindAncestor}, Mode=TwoWay}" 
                                                 Value="{x:Static enum:Match.None}">
                                        <Setter Property="IsExpanded" Value="True"/>
                                    </DataTrigger>
                                    <DataTrigger Binding="{Binding DataContext.Item.Match, RelativeSource={RelativeSource AncestorType={x:Type UserControl}, Mode=FindAncestor}, Mode=TwoWay}" 
                                                 Value="{x:Static enum:Match.Exact}">
                                        <Setter Property="IsExpanded" Value="True"/>
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </Expander.Style>
                        <WrapPanel Orientation="Horizontal" Background="Transparent">
                            <view:InformationView Margin="0 0 20 0"/>
                            <view:ProceduresView Margin="0 0 0 0" />
                        </WrapPanel>
                     </Expander>

这似乎可以正常工作,直到我们手动展开可扩展区域后。此后,数据触发器似乎被忽略了,手动设置的IsExpanded属性将不会更改,直到用户再次手动打开或关闭可扩展区域。
我希望用户能够手动展开或关闭它,但我希望数据触发器优先于用户输入。
注意:我不希望通过IsExpanded属性更改Match的值。Match是单独更新的,但其值影响IsExpanded。
2个回答

2
这是因为绑定在而不是属性上,所以更改对的绑定属性没有影响。

绑定到属性,并使用自定义在源枚举和展开器布尔值之间进行双向转换。

参见:https://learn.microsoft.com/en-us/uwp/api/windows.ui.xaml.data.ivalueconverter

作为一个很好的副作用,您将得到更短,更易于阅读的XAML。

更新

要实现所需的行为,在ViewModel上具有一个布尔属性,用于展开状态,并将其双向绑定到的属性,并在属性更改时在ViewModel中更改它。这样,用户和ViewModel都可以修改的状态。

类似以下内容:

public bool IsExpanded
{
    get => _isExpanded;
    set
    {
        _isExpanded = value;
        OnPropertyChanged(nameof(IsExpanded));
    }
}

public Match Match
{
    get => _match;
    set
    {
       _match = value;
       switch (value)
       {
           case Exact:
           case None:
               IsExpanded = true;
               break;
           case Multiple:
               IsExpanded = false;
               break;
       }
    }
}

我们不希望通过IsExpanded属性改变Match的值。Match是单独更新的,但它的值会影响到IsExpanded。 - Ben
Match 的哪些值允许用户手动打开/关闭 Expander - Scroog1
如果“Match”有一个值,表示是否展开,似乎没有用户可以选择不覆盖的空间。 - Scroog1
你的意思是Match中的更改会覆盖当前状态,但用户可以在Match更改之间修改状态吗? - Scroog1
用户应该始终能够展开或关闭扩展器,但是每当“匹配”值发生变化时,扩展器应该更改为正确的状态:无和精确应将IsExpanded设置为true,而无则将其设置为false。 - Ben
显示剩余3条评论

0
视图模型不应该依赖于视图。也就是说,您不应该像Scroog的答案建议的那样添加一个IsExpanded属性。
我通过一个行为类解决了一个非常类似的问题,该类根据Expander的IsEnabled属性更改IsExpanded。因此,这只在视图中实现。
以下类仅为示例,可以通过添加绑定到视图模型的任何属性来增强它,而不是检查IsEnabled。
public class AutoExpandBehaviour 
{
    public static readonly DependencyProperty AutoExpandProperty =
            DependencyProperty.RegisterAttached(
            "AutoExpand",
            typeof(bool),
            typeof(AutoExpandBehaviour),
            new UIPropertyMetadata(false, AutoExpandChanged));

    public static bool GetAutoExpand(Expander expander)
    {
        return (bool)expander.GetValue(AutoExpandProperty);
    }

    public static void SetAutoExpand(Expander expander, bool value)
    {
        expander.SetValue(AutoExpandProperty, value);
    }

    static void AutoExpandChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
    {
        var expander = depObj as Expander;
        if (expander == null)
        {
            return;
        }

        if (e.NewValue is bool == false)
            return;

        if ((bool)e.NewValue)
        {
            expander.IsEnabledChanged += Item_IsEnabledChanged;
        }
        else
        {
            expander.IsEnabledChanged -= Item_IsEnabledChanged;
        }
    }

    private static void Item_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        var expander = sender as Expander;
        if (expander != null)
        {
            expander.IsExpanded = (bool)e.NewValue;
        }
    }
}

在 XAML 中使用:

        <Expander IsEnabled="{Binding IsFunctionAvailable}" 
              local:AutoExpandBehaviour.AutoExpand="True"
              ... >
            ...
        </Expander>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接