Reputation: 975
I created an attached property for ListBox like this:
using ListBoxControl = System.Windows.Controls.ListBox;
namespace App.Ui.Views.AttachedProperties
{
public class ListBox
{
public static readonly DependencyProperty autoScrollProperty =
DependencyProperty.RegisterAttached(
"AutoScroll",
typeof(bool),
typeof(ListBoxControl),
new PropertyMetadata(false));
public static void SetAutoScroll(ListBoxControl element, bool value)
{
element.SetValue(autoScrollProperty, value);
if (value)
{
element.SelectionChanged += Element_SelectionChanged;
}
else
{
element.SelectionChanged -= Element_SelectionChanged;
}
}
public static bool GetAutoScroll(ListBoxControl element)
{
return (bool)element.GetValue(autoScrollProperty);
}
private static void Element_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var listBox = (ListBoxControl)sender;
listBox.ScrollIntoView(listBox.SelectedItem);
}
}
}
When I use a static True/False value in the xaml, it works fine:
<ListBox ap:ListBox.AutoScroll="True">
...
</ListBox>
But if I data bind to a property in my view model:
<ListBox ap:ListBox.AutoScroll="{Binding Path=Settings.EnableAutoScroll}">
...
</ListBox>
Then I get the following exception: A 'Binding' cannot be set on the 'SetAutoScroll' property of type 'ListBox'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.
Is this possible, or am I going to need to derive my own custom list box to accomplish this?
Upvotes: 0
Views: 132
Reputation: 414
Problem in this line typeof(ListBoxControl)
. You should specify the name of the class where custom attached property seats.
I would recommend rename class from ListBox to ListBoxExtensions, also, make it static. Then you don't have to use alias ListBoxControl.
Your final code will look like:
public static class ListBoxExtensions
{
public static readonly DependencyProperty autoScrollProperty =
DependencyProperty.RegisterAttached(
"AutoScroll",
typeof(bool),
typeof(ListBoxExtensions),
new PropertyMetadata(false));
...
}
Edit:
OK, your code has another problem.
Remove attachment of the listener from setter (SetAutoScroll
) and put this logic into dependency property callback.
public static class ListBoxExtensions
{
public static readonly DependencyProperty autoScrollProperty =
DependencyProperty.RegisterAttached(
"AutoScroll",
typeof(bool),
typeof(ListBoxExtensions),
new PropertyMetadata(false, AutoScrollChangedCallback));
public static void SetAutoScroll(ListBox element, bool value)
{
element.SetValue(autoScrollProperty, value);
}
public static bool GetAutoScroll(ListBox element)
{
return (bool)element.GetValue(autoScrollProperty);
}
private static void AutoScrollChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
ListBox control = (ListBox)d;
if ((bool)e.NewValue)
{
control.SelectionChanged += Element_SelectionChanged;
}
else
{
control.SelectionChanged -= Element_SelectionChanged;
}
}
private static void Element_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var listBox = (ListBox)sender;
listBox.ScrollIntoView(listBox.SelectedItem);
}
}
Upvotes: 1