C# WPF扩展器在用户交互后忽略数据绑定
我有一个带有扩展器的WPF应用程序,我想在其中更改IsExpanded属性 基于我的视图模型中的枚举值,即我希望扩展器根据 此枚举属性无效。我在xaml中使用数据触发器来更新IsExpanded属性 关于我的枚举支持属性的值C# WPF扩展器在用户交互后忽略数据绑定,c#,wpf,xaml,C#,Wpf,Xaml,我有一个带有扩展器的WPF应用程序,我想在其中更改IsExpanded属性 基于我的视图模型中的枚举值,即我希望扩展器根据 此枚举属性无效。我在xaml中使用数据触发器来更新IsExpanded属性 关于我的枚举支持属性的值 <Expander Header="Information and Procedures" BorderThickness="0" Margin="
<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这是因为绑定在
DataTrigger
上,而不是IsExpanded
属性上,因此更改IsExpanded
不会影响DataTrigger
绑定属性
<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
属性,并使用自定义IValueConverter
在源枚举和扩展器布尔之间进行双向转换
见:
作为一个很好的副作用,您还将得到更短、更易于阅读的XAML
更新
要实现所需的行为,请在viewmodel上为展开状态设置一个布尔属性,该属性双向绑定到Expander
的IsExpanded
属性,并在Match
属性更改时在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;
}
}
}
视图模型不应依赖于视图。也就是说,您不应该像Scroog的回答所建议的那样添加IsExpanded属性
我通过一个行为类解决了一个非常类似的问题,该行为类根据扩展器的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>
...
我们不希望IsExpanded属性更改Match的值。Match单独更新,但其值会影响ISExpanded,其中Match
的值允许用户手动打开/关闭扩展器
?如果Match
的值表示已展开或未展开,似乎没有任何空间供用户进行非重写选择。或者您的意思是,Match
中的更改会重写当前状态,但用户可以修改Match
更改之间的状态?用户应该始终能够展开或关闭扩展器,但是只要Match的值发生更改,扩展器应更改为正确的状态:None和Exact应将IsExpanded设置为true,None将其设置为false