Когда нажмите кнопку, чтобы отобразить группировку (прокрутите список до нужного места, но после сортировки он не выполняется
У меня есть список с использованием в качестве источника ListCollectionView
Мой ListBox использует GroupStyle, который выглядит как
<GroupBox Tag="{Binding Path=Items[0].Header}">
<GroupBox.Header>
<TextBlock Text="{Binding Path=Items[0].Header}" FontStyle="Italic" Foreground="Gray" FontSize="13" />
</GroupBox.Header>
<ItemsPresenter />
</GroupBox>
Применяется так
<ListBox.GroupStyle>
<GroupStyle ContainerStyle="{StaticResource GroupHeaderStyle}"/>
</ListBox.GroupStyle>
Теперь у меня есть кнопка, которая при нажатии должна вывести на экран определенную группу (прокрутите список до нужного места)
foreach (var groupBox in FindVisualChildren<GroupBox>(this))
{
if (groupBox.Tag.ToString() == "M")
groupBox.BringIntoView();
}
это прекрасно работает Однако, если в моем событии нажатия кнопки я меняю свой вид
MyVm.MyView.GroupDescriptions.Clear();
MyVm.MyView.SortDescriptions.Clear();
MyVm.MyView.GroupDescriptions.Add(new PropertyGroupDescription("Header"));
MyVm.MyView.SortDescriptions.Add(new SortDescription("Header", ListSortDirection.Descending));
MyVm.MyView.SortDescriptions.Add(new SortDescription("Data", ListSortDirection.Descending));
а затем сразу же снова попробуйте BringIntoView соответствующий групповой ящик, групповой ящик не найден. FindVisualChildren не находит групповые блоки, только элементы группы.
Полный код
XAML:
<Window.Resources>
<Style x:Key="GroupHeaderStyle" x:Shared="False" TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<GroupBox Tag="{Binding Path=Items[0].Header}">
<GroupBox.Header>
<TextBlock Text="{Binding Path=Items[0].Header}" FontStyle="Italic" Foreground="Gray" FontSize="13" />
</GroupBox.Header>
<ItemsPresenter />
</GroupBox>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<StackPanel Orientation="Vertical">
<Button Click="ButtonBase_OnClick" Content="Bring M into view"></Button>
<ScrollViewer>
<ListBox MaxHeight="300" ItemsSource="{Binding MyView}">
<ListBox.GroupStyle>
<GroupStyle ContainerStyle="{StaticResource GroupHeaderStyle}"/>
</ListBox.GroupStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Data}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</ScrollViewer>
</StackPanel>
Код позади:
public partial class MainWindow : Window
{
private ListVm MyVm;
public MainWindow()
{
InitializeComponent();
MyVm = new ListVm();
DataContext = MyVm;
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
//THIS WORKS
foreach (var groupBox in FindVisualChildren<GroupBox>(this))
{
if (groupBox.Tag.ToString() == "L")
groupBox.BringIntoView();
}
//THIS DOES NOT
//MyVm.MyView.GroupDescriptions.Clear();
//MyVm.MyView.SortDescriptions.Clear();
//MyVm.MyView.GroupDescriptions.Add(new PropertyGroupDescription("Header"));
//MyVm.MyView.SortDescriptions.Add(new SortDescription("Header", ListSortDirection.Descending));
//MyVm.MyView.SortDescriptions.Add(new SortDescription("Data", ListSortDirection.Descending));
//foreach (var groupBox in FindVisualChildren<GroupBox>(this))
//{
// if (groupBox.Tag.ToString() == "B")
// groupBox.BringIntoView();
//}
}
public IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
public static T FindChild<T>(DependencyObject parent, string childName) where T : DependencyObject
{
// Confirm parent and childName are valid.
if (parent == null) return null;
T foundChild = null;
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
// If the child is not of the request child type child
T childType = child as T;
if (childType == null)
{
// recursively drill down the tree
foundChild = FindChild<T>(child, childName);
// If the child is found, break so we do not overwrite the found child.
if (foundChild != null) break;
}
else if (!string.IsNullOrEmpty(childName))
{
var frameworkElement = child as FrameworkElement;
// If the child's name is set for search
if (frameworkElement != null && frameworkElement.Name == childName)
{
// if the child's name is of the request name
foundChild = (T)child;
break;
}
}
else
{
// child element found.
foundChild = (T)child;
break;
}
}
return foundChild;
}
}
public class ItemVm
{
public string Header { get; set; }
public string Data { get; set; }
public ItemVm(string data)
{
Data = data;
Header = Data.Substring(0, 1);
}
}
public class ListVm
{
public ListCollectionView MyView { get; set; }
public ObservableCollection<ItemVm> MyList { get; set; }
public ListVm()
{
MyList = new ObservableCollection<ItemVm>();
MyList.Add(new ItemVm("Apple"));
MyList.Add(new ItemVm("Banana"));
MyList.Add(new ItemVm("Charlie"));
MyList.Add(new ItemVm("Delta"));
MyList.Add(new ItemVm("Echo"));
MyList.Add(new ItemVm("Foxtrot"));
MyList.Add(new ItemVm("Golf"));
MyList.Add(new ItemVm("Hotel"));
MyList.Add(new ItemVm("Index"));
MyList.Add(new ItemVm("Jarjar"));
MyList.Add(new ItemVm("Kilo"));
MyList.Add(new ItemVm("Lima"));
MyList.Add(new ItemVm("Monaco"));
MyList.Add(new ItemVm("Noob"));
MyView = (ListCollectionView)CollectionViewSource.GetDefaultView(MyList);
MyView.GroupDescriptions.Add(new PropertyGroupDescription("Header"));
MyView.SortDescriptions.Add(new SortDescription("Header", ListSortDirection.Ascending));
MyView.SortDescriptions.Add(new SortDescription("Data", ListSortDirection.Ascending));
}
}