Reputation: 285
I am building what I have learned is basically an accordion control, with a selection mode that ensures that only one section is open at the time. Each section is implemented using Expander controls, so if on Expander is opened, all others should close.
I have done that in the following manner:
While the converter methods executes successfully, the problem is the DependencyProperty ControlValue is never set even though it binds successfully to a value and don't raise any errors. I have confirmed this through various debugging. So the result is that all sections are stuck with the default value, rendering the accordion selection behavior I want, useless.
Why is the DependencyProperty binding being ignored? Is it because it is defined within a binding, or something else?
Remarks
Everything is data-driven, and worked great in static a mockup I did before implementing the generic data-driven version. A fully data driven solution is a must, so using one way multi bindings or hardcoded XAML parameters (the solutions I have been able to find for related issues) is not an option.
It is important to note that all other bindings work perfect, so there is no problem DataContext wise. As everything should work (in my mind), this is also why I have not gone the WPF Toolkit Accordion way yet, so please do not suggest this initially (unless it is really the only way). First of, being new to WPF, I would like to understand why this is not working.
XAML (extract - some names changed to obfuscate business meaning - central part is IsExpanded binding):
<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>
Converter (simplified)
public class TestConverter : DependencyObject, IValueConverter
{
public static readonly DependencyProperty ControlValueProperty = DependencyProperty.Register("ControlValue", typeof(short), typeof(TestConverter), new PropertyMetadata(default(short)));
public short ControlValue
{
get { return (short) GetValue(ControlValueProperty); }
set { SetValue(ControlValueProperty, value); }
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (short)value==ControlValue;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return (bool)value ? ControlValue : Binding.DoNothing;
}
}
ActiveQuestionId implementation in ViewModel - INotifyPropertyChanged is tested and works, ViewModel is DataContext on Parent UserControl
private short activeQuestionId;
public short ActiveQuestionId
{
get
{
return activeQuestionId;
}
set
{
if (value != activeQuestionId)
{
activeQuestionId = value;
OnPropertyChanged();
}
}
}
Upvotes: 1
Views: 1312
Reputation: 128061
The current DataContext value is not inherited down to the TestConverter instance.
You may avoid this complex binding altogether and implement your control by using a ListBox:
<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>
Upvotes: 2