Programatically add MultipleChoiceFilter #71
Unanswered
vaclav-domin
asked this question in
Q&A
Replies: 4 comments 5 replies
-
Hard to say with these partial code fragments. Can you share a demo project? |
Beta Was this translation helpful? Give feedback.
0 replies
-
The MultipleChoiceFilter is not the template of the column! |
Beta Was this translation helpful? Give feedback.
2 replies
-
I tested and problem is in behaviour from other side for SelectedItems in
DataGrid and ListBox.
if I don't use this, all works fine.
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
namespace Lesma3.AttachedBehaviors
{
public class DataGridSelecteItemsBehavior : DependencyObject
{
public static readonly DependencyProperty
IsSubscribedToSelectionChangedProperty =
DependencyProperty.RegisterAttached(
"IsSubscribedToSelectionChanged", typeof(bool),
typeof(DataGridSelecteItemsBehavior), new PropertyMetadata(default(bool)));
public static void
SetIsSubscribedToSelectionChanged(DependencyObject element, bool value) {
element.SetValue(IsSubscribedToSelectionChangedProperty, value); }
public static bool
GetIsSubscribedToSelectionChanged(DependencyObject element) { return
(bool)element.GetValue(IsSubscribedToSelectionChangedProperty); }
public static readonly DependencyProperty SelectedItemsProperty =
DependencyProperty.RegisterAttached(
"SelectedItems", typeof(IList),
typeof(DataGridSelecteItemsBehavior), new PropertyMetadata(default(IList),
OnSelectedItemsChanged));
public static void SetSelectedItems(DependencyObject element, IList
value) { element.SetValue(SelectedItemsProperty, value); }
public static IList GetSelectedItems(DependencyObject element) {
return (IList)element.GetValue(SelectedItemsProperty); }
/// <summary>
/// Attaches a list or observable collection to the grid or
listbox, syncing both lists (one way sync for simple lists).
/// </summary>
/// <param name="d">The DataGrid or ListBox</param>
/// <param name="e">The list to sync to.</param>
private static void OnSelectedItemsChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
if (!(d is ListBox || d is MultiSelector))
throw new ArgumentException("Somehow this got attached to
an object I don't support. ListBoxes and Multiselectors (DataGrid), people.
Geesh =P!");
var selector = (Selector)d;
var oldList = e.OldValue as IList;
if (oldList != null)
{
var obs = oldList as INotifyCollectionChanged;
if (obs != null)
{
obs.CollectionChanged -= OnCollectionChanged;
}
// If we're orphaned, disconnect lb/dg events.
if (e.NewValue == null)
{
selector.SelectionChanged -= OnSelectorSelectionChanged;
SetIsSubscribedToSelectionChanged(selector, false);
}
}
var newList = (IList)e.NewValue;
if (newList != null)
{
var obs = newList as INotifyCollectionChanged;
if (obs != null)
{
obs.CollectionChanged += OnCollectionChanged;
}
PushCollectionDataToSelectedItems(newList, selector);
var isSubscribed =
GetIsSubscribedToSelectionChanged(selector);
if (!isSubscribed)
{
selector.SelectionChanged += OnSelectorSelectionChanged;
SetIsSubscribedToSelectionChanged(selector, true);
}
}
}
/// <summary>
/// Initially set the selected items to the items in the newly
connected collection,
/// unless the new collection has no selected items and the
listbox/grid does, in which case
/// the flow is reversed. The data holder sets the state. If both
sides hold data, then the
/// bound IList wins and dominates the helpless wpf control.
/// </summary>
/// <param name="obs">The list to sync to</param>
/// <param name="selector">The grid or listbox</param>
private static void PushCollectionDataToSelectedItems(IList obs,
DependencyObject selector)
{
var listBox = selector as ListBox;
if (listBox != null)
{
if (obs.Count > 0)
{
listBox.SelectedItems.Clear();
foreach (var ob in obs) {
listBox.SelectedItems.Add(ob); }
}
else
{
foreach (var ob in listBox.SelectedItems) {
obs.Add(ob); }
}
return;
}
// Maybe other things will use the multiselector base... who
knows =P
var grid = selector as MultiSelector;
if (grid != null)
{
if (obs.Count > 0)
{
grid.SelectedItems.Clear();
foreach (var ob in obs) { grid.SelectedItems.Add(ob); }
}
else
{
foreach (var ob in grid.SelectedItems) { obs.Add(ob); }
}
return;
}
throw new ArgumentException("Somehow this got attached to an
object I don't support. ListBoxes and Multiselectors (DataGrid), people.
Geesh =P!");
}
/// <summary>
/// When the listbox or grid fires a selectionChanged even, we
update the attached list to
/// match it.
/// </summary>
/// <param name="sender">The listbox or grid</param>
/// <param name="e">Items added and removed.</param>
private static void OnSelectorSelectionChanged(object sender,
SelectionChangedEventArgs e)
{
var dep = (DependencyObject)sender;
var items = GetSelectedItems(dep);
var col = items as INotifyCollectionChanged;
// Remove the events so we don't fire back and forth, then
re-add them.
if (col != null) col.CollectionChanged -= OnCollectionChanged;
foreach (var oldItem in e.RemovedItems) items.Remove(oldItem);
foreach (var newItem in e.AddedItems) items.Add(newItem);
if (col != null) col.CollectionChanged += OnCollectionChanged;
}
/// <summary>
/// When the attached object implements INotifyCollectionChanged,
the attached listbox
/// or grid will have its selectedItems adjusted by this handler.
/// </summary>
/// <param name="sender">The listbox or grid</param>
/// <param name="e">The added and removed items</param>
private static void OnCollectionChanged(object sender,
NotifyCollectionChangedEventArgs e)
{
// Push the changes to the selected item.
var listbox = sender as ListBox;
if (listbox != null)
{
listbox.SelectionChanged -= OnSelectorSelectionChanged;
if (e.Action == NotifyCollectionChangedAction.Reset)
listbox.SelectedItems.Clear();
else
{
foreach (var oldItem in e.OldItems)
listbox.SelectedItems.Remove(oldItem);
foreach (var newItem in e.NewItems)
listbox.SelectedItems.Add(newItem);
}
listbox.SelectionChanged += OnSelectorSelectionChanged;
}
var grid = sender as MultiSelector;
if (grid != null)
{
grid.SelectionChanged -= OnSelectorSelectionChanged;
if (e.Action == NotifyCollectionChangedAction.Reset)
grid.SelectedItems.Clear();
else
{
foreach (var oldItem in e.OldItems)
grid.SelectedItems.Remove(oldItem);
foreach (var newItem in e.NewItems)
grid.SelectedItems.Add(newItem);
}
grid.SelectionChanged += OnSelectorSelectionChanged;
}
}
}
}
****************************
S přáním příjemného zbytku dne...
Ing. Václav Domin
http://potapeni.na.jihu.cz http://www.octopus-cb.cz
út 24. 8. 2021 v 19:00 odesílatel tom-englert ***@***.***>
napsal:
… The MultipleChoiceFilter is not the template of the column!
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#71 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AC3PW4EIP6CKXARPL77INEDT6PF3NANCNFSM5CW2M3WQ>
.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&utm_campaign=notification-email>
.
|
Beta Was this translation helpful? Give feedback.
1 reply
-
Works great when you remove the |
Beta Was this translation helpful? Give feedback.
2 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Quetion:
I create columns programatically.
Data are collection of derived types.
How add MultipleChoiceFilter?
In My Code:
GridColumns.Add(new DataGridTextColumn() { Header = txt.hdrKod, Binding = new Binding("Kod"), Width = 50, DisplayIndex = 0 });
GridColumns[0].SetTemplate(App.Current.Resources["MultipleChoiceFilter"] as System.Windows.Controls.ControlTemplate);
After bind data I got error on DatagridSelectedItemBehaviour.OnSelectorSelectionChanged on items.Add(newItem): Value is not type XXXX and cann't use on generic collection.
Where XXXX is name of class, The property "Kod" is string.
Beta Was this translation helpful? Give feedback.
All reactions