C# 为什么值转换器上的WPF自定义DependencyProperty绑定未执行?
我正在构建我所学到的基本上是一个手风琴控件,带有一个选择模式,确保在同一时间只有一个部分打开。每个部分都是使用扩展器控件实现的,所以如果打开了扩展器上的,所有其他部分都应该关闭 我是通过以下方式做到这一点的:C# 为什么值转换器上的WPF自定义DependencyProperty绑定未执行?,c#,wpf,data-binding,dependency-properties,ivalueconverter,C#,Wpf,Data Binding,Dependency Properties,Ivalueconverter,我正在构建我所学到的基本上是一个手风琴控件,带有一个选择模式,确保在同一时间只有一个部分打开。每个部分都是使用扩展器控件实现的,所以如果打开了扩展器上的,所有其他部分都应该关闭 我是通过以下方式做到这一点的: 在视图模型(实现INotifyPropertyChanged)上添加了表示当前打开节的Id的属性ActiveQuestionId 创建了从DependencyObject继承的转换器,该转换器能够将ActiveQuestionId转换为布尔值,指示是否应打开特定节,方法是向转换器添加De
- 在视图模型(实现INotifyPropertyChanged)上添加了表示当前打开节的Id的属性ActiveQuestionId
- 创建了从DependencyObject继承的转换器,该转换器能够将ActiveQuestionId转换为布尔值,指示是否应打开特定节,方法是向转换器添加DependencyProperty ControlValue,指示该节所属的节
- 为每个节创建本地转换器,并将ControlValue绑定到其节的QuestionId
<ItemsControl ItemsSource="{Binding QuestionSection.QuestionAssignments}"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
Style="{x:Null}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="{StaticResource Grey400Brush}"
BorderThickness="0 1 0 0">
<Expander Background="{StaticResource Grey200Brush}"
Foreground="Black"
Padding="0"
Margin="0">
<Expander.IsExpanded>
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType=views:TypeOfParentControl}"
Path="DataContext.ActiveQuestionId"
Mode="TwoWay">
<Binding.Converter>
<converters:TestConverter ControlValue="{Binding QuestionId}"/>
</Binding.Converter>
</Binding>
</Expander.IsExpanded>
<Expander.HeaderTemplate>
<!--Custom Styling Here, All Bindings Work-->
</Expander.HeaderTemplate>
<!--Content Here, All Bindings Work-->
</Expander>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
ViewModel中的ActiveQuestionId实现-INotifyPropertyChanged已测试并运行,ViewModel是父用户控件上的DataContext
private short activeQuestionId;
public short ActiveQuestionId
{
get
{
return activeQuestionId;
}
set
{
if (value != activeQuestionId)
{
activeQuestionId = value;
OnPropertyChanged();
}
}
}
当前DataContext值不会向下继承到TestConverter实例 您可以完全避免这种复杂的绑定,并通过使用列表框实现您的控件:
<ListBox ItemsSource="{Binding QuestionSection.QuestionAssignments}"
SelectedValuePath="QuestionId"
SelectedValue="{Binding ActiveQuestionId}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Expander IsExpanded="{Binding IsSelected,
RelativeSource={RelativeSource TemplatedParent}}">
...
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
...
可能当前DataContext值没有继承到TestConverter实例。您也许可以通过使用IMultiValueConverter的多重绑定来更好地解决这个问题。@Clemens可能不是,这是因为它在绑定中吗?如果绑定到任何其他元素,DataContext工作正常,即绑定到QuestionAssignment类上的QuestionId属性。我确实尝试过多重绑定,但意识到它并没有以支持我的用例的方式真正支持ConvertBack。也就是说,如果IsExpanded设置为true,我需要在视图模型上设置(ConvertBack)ActiveQuestionId,如果设置为false,则什么也不做。否则,不会通知其他部分有关更改。如果不考虑MVVM,我当然可以实现这一点,但我希望保持事物的解耦。如果希望转换器参与继承上下文,请尝试在扩展器中将其声明为资源。您还需要使其扩展Freezable
而不是DependencyObject
@MikeStrobel感谢您的输入,我尝试使用带有x:Shared=“False”的模板方法中的资源,根据我目前的理解,应该为每个项目创建一个单独的转换器实例。我没有使用Freezable,我将研究该类,但现在选择使用一个列表框,因为它符合我的开箱即用的需要,在我的情况下是一个更优雅的解决方案。@SuppaiKamo听起来不错。仅供参考,Freezable
是参与继承上下文的最高级类,因此,如果您想将对象用作绑定目标,它必须派生自该类。该类工作非常出色,显然是适合我的用例的方法,谢谢。我需要更好地了解我的控件的功能:)
<ListBox ItemsSource="{Binding QuestionSection.QuestionAssignments}"
SelectedValuePath="QuestionId"
SelectedValue="{Binding ActiveQuestionId}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Expander IsExpanded="{Binding IsSelected,
RelativeSource={RelativeSource TemplatedParent}}">
...
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>