我有一个自定义ListView控件,该控件将ModelItems的列表作为其ItemsSource:
name
我还有一个依赖项属性def 'all events are published to subscribers'() {
given:
EventSubscriber subscriber = Mock()
subscriber.shouldRegister() >> true
subscriber.interests() >> new HashSet<Intent>(Arrays.asList(COUNTER, GAUGE))
publisher.subscribe(subscriber)
when:
def event = publisher.newEvent('test', COUNTER)
event.start()
event.newChild('child', GAUGE)
event.finish()
then:
1 * subscriber.onCreate({ it.name == 'test' })
1 * subscriber.onCreate({ it.name == 'child' })
1 * subscriber.onStart({ it.name == 'test' }, !null)
1 * subscriber.onEnd({ it.name == 'test' }, !null)
1 * subscriber.onChild({ it.name == 'test' }, { it.name == 'child' })
}
,其属性类型为 <customControls:ListViewEx Name="DocumentListView"
ItemsSource="{Binding ModelItems, Mode=OneWay}">
:
GridViewColumnHeaderClick.HeaderClick
我希望将object
作为值传递给此依赖项属性,而我试图这样做:
public static readonly DependencyProperty HeaderClickProperty = DependencyProperty.RegisterAttached(
"HeaderClick",
typeof(object),
typeof(GridViewColumnHeaderClick),
new UIPropertyMetadata(null, OnHeaderClickChanged));
和在C#中:
ModelItems
但是,当我单击标题时似乎什么也没发生。我不确定是否是因为我在XAML中错误地绑定了它,或者是完全不同的东西。
编辑:抱歉,没有提供详细信息,我知道这有点混乱。
我的总体目标是通过单击GridViewColumn的标题来运行排序功能。 <GridView.ColumnHeaderContainerStyle>
<Style BasedOn="{StaticResource {x:Type GridViewColumnHeader}}" TargetType="{x:Type GridViewColumnHeader}">
<Setter Property = "misc:GridViewColumnHeaderClick.HeaderClick"
Value="{Binding ModelItems}"/>
</Style>
</GridView.ColumnHeaderContainerStyle>
是 ICollectionView dataView =
CollectionViewSource.GetDefaultView(HeaderClickProperty);
的子级。单击标题后,我希望将其绑定到GridView
属性,并将值设置为ListViewEx
的{{1}}(在本例中为HeaderClick
),以便可以解决。
单击功能ItemsSource
会运行:
ListView
这会将功能ItemsSource=ModelItems
添加到OnHeaderClickChanged
事件中。此功能是使用 private static void OnHeaderClickChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
var headerClicked = sender as GridViewColumnHeader;
headerClicked.MouseUp += (s, me) => HeaderClickedOnMouseUp(s, me, e.NewValue);
}
进行排序的功能。
我的问题是我对依赖项/附加属性以及如何将其与视图绑定缺乏了解。正如评论中正确提到的那样,当我尝试调试setter时,不会在任何时候调用它,并且我不知道为什么会发生这种情况。
答案 0 :(得分:1)
这是一个使用升序排序的简单排序示例。附加属性Sort.IsEnabled
应该在GridViewColumnHeader
上设置。
排序本身是通过设置列的父项SortDescription
的默认CollectionView
的{{1}}来完成的。
推荐阅读:
Attached Properties Overview
Dependency properties overview
数据模型: Person.cs
ListView.ItemsSource
ViewModel.cs
class Person
{
public Person(string firstName, string lastName)
{
this.FirstName = firstName;
this.LastName = lastName;
}
public string FirstName { get; set; }
public string LastName { get; set; }
}
附加属性class ViewModel : INotifyPropertyChanged
{
public ViewModel()
{
this.Persons = new ObservableCollection<Person>()
{
new Person("Derek", "Zoolander"),
new Person("Tony", "Montana"),
new Person("The", "Dude")
};
}
public ObservableCollection<Person> Persons { get; set; }
}
:
Sort.cs
Sort
扩展助手方法来查找可视父对象: Extensions.cs
class Sort : DependencyObject
{
#region IsEnabled attached property
public static readonly DependencyProperty IsEnabledProperty = DependencyProperty.RegisterAttached(
"IsEnabled", typeof(bool), typeof(Sort), new PropertyMetadata(false, Sort.OnIsEnabled));
public static void SetIsEnabled([NotNull] DependencyObject attachingElement, bool value) => attachingElement.SetValue(Sort.IsEnabledProperty, value);
public static bool GetIsEnabled([NotNull] DependencyObject attachingElement) => (bool) attachingElement.GetValue(Sort.IsEnabledProperty);
#endregion
private static void OnIsEnabled(DependencyObject attachingElement, DependencyPropertyChangedEventArgs e)
{
bool isSortingEnabled = (bool) e.NewValue;
if (isSortingEnabled == (bool) e.OldValue)
{
return;
}
if (attachingElement is GridViewColumnHeader columnHeader)
{
if (isSortingEnabled)
{
columnHeader.Click += Sort.SortByColumn;
}
else
{
columnHeader.Click -= Sort.SortByColumn;
}
}
}
private static void SortByColumn(object sender, RoutedEventArgs e)
{
var columnHeader = sender as GridViewColumnHeader;
PropertyPath columnSourceProperty = (columnHeader.Column.DisplayMemberBinding as Binding).Path;
// Use an extension method to find the parent ListView
// by traversing the visual tree
if (columnHeader.TryFindVisualParentElement(out ListView parentListView))
{
var collectionView = (CollectionView)CollectionViewSource.GetDefaultView(parentListView.ItemsSource);
collectionView.SortDescriptions.Clear();
// Apply sorting
collectionView.SortDescriptions.Add(new SortDescription(columnSourceProperty.Path, ListSortDirection.Ascending));
}
}
}
用法: MainWindow.xaml
public static class Extensions
{
/// <summary>
/// Traverses the visual tree towards the root until an element with a matching element name is found.
/// </summary>
/// <typeparam name="TParent">The type the visual parent must match.</typeparam>
/// <param name="child"></param>
/// <param name="resultElement"></param>
/// <returns><c>true</c> when the parent visual was found otherwise <c>false</c></returns>
public static bool TryFindVisualParentElement<TParent>(this DependencyObject child, out TParent resultElement)
where TParent : DependencyObject
{
resultElement = null;
DependencyObject parentElement = VisualTreeHelper.GetParent(child);
if (parentElement is TParent parent)
{
resultElement = parent;
return true;
}
return parentElement?.TryFindVisualParentElement(out resultElement) ?? false;
}
}