Click here to Skip to main content
15,919,028 members
Home / Discussions / WPF
   

WPF

 
QuestionHow to have duplicate model/view-model in TabControl Pin
Leif Simon Goodwin21-Apr-16 2:01
Leif Simon Goodwin21-Apr-16 2:01 
AnswerRe: How to have duplicate model/view-model in TabControl Pin
Pete O'Hanlon21-Apr-16 3:57
mvePete O'Hanlon21-Apr-16 3:57 
GeneralRe: How to have duplicate model/view-model in TabControl Pin
Leif Simon Goodwin22-Apr-16 0:41
Leif Simon Goodwin22-Apr-16 0:41 
GeneralRe: How to have duplicate model/view-model in TabControl Pin
Pete O'Hanlon22-Apr-16 0:44
mvePete O'Hanlon22-Apr-16 0:44 
QuestionWPF App for video recording from webcam into file MP4/h.264 Pin
Qinitram13-Apr-16 23:33
Qinitram13-Apr-16 23:33 
AnswerRe: WPF App for video recording from webcam into file MP4/h.264 Pin
Gerry Schmitz17-Apr-16 19:31
mveGerry Schmitz17-Apr-16 19:31 
QuestionUserControl not displayed inside the parent window only in designer Pin
hesido9-Apr-16 0:18
hesido9-Apr-16 0:18 
QuestionLoading resources from XAML, problem with fonts Pin
Jayme655-Apr-16 10:17
Jayme655-Apr-16 10:17 
AnswerRe: Loading resources from XAML, problem with fonts Pin
Pete O'Hanlon5-Apr-16 21:49
mvePete O'Hanlon5-Apr-16 21:49 
QuestionCombox with Multi Column Header Pin
fratola29-Mar-16 8:08
fratola29-Mar-16 8:08 
AnswerRe: Combox with Multi Column Header Pin
Richard Deeming29-Mar-16 8:26
mveRichard Deeming29-Mar-16 8:26 
GeneralRe: Combox with Multi Column Header Pin
fratola31-Mar-16 20:26
fratola31-Mar-16 20:26 
Questionlistviewitem style Pin
caradri13-Mar-16 0:41
caradri13-Mar-16 0:41 
Questionxceed datagrid (community) and virtualization Pin
amigoface9-Mar-16 18:47
amigoface9-Mar-16 18:47 
AnswerRe: window application form work in KIOSK Pin
Pete O'Hanlon8-Feb-16 21:37
mvePete O'Hanlon8-Feb-16 21:37 
AnswerRe: window application form work in KIOSK Pin
Richard Deeming9-Feb-16 1:55
mveRichard Deeming9-Feb-16 1:55 
AnswerRe: window application form work in KIOSK Pin
ZurdoDev9-Feb-16 8:36
professionalZurdoDev9-Feb-16 8:36 
QuestionHow to Programatically click a Button on a navigated Frame Page Pin
Vimalsoft(Pty) Ltd14-Jan-16 3:22
professionalVimalsoft(Pty) Ltd14-Jan-16 3:22 
AnswerRe: How to Programatically click a Button on a navigated Frame Page Pin
Vimalsoft(Pty) Ltd14-Jan-16 5:40
professionalVimalsoft(Pty) Ltd14-Jan-16 5:40 
QuestionCustom FrameworkElement with child controls Pin
Kenneth Haugland12-Jan-16 7:51
mvaKenneth Haugland12-Jan-16 7:51 
AnswerRe: Custom FrameworkElement with child controls Pin
Gerry Schmitz12-Jan-16 17:06
mveGerry Schmitz12-Jan-16 17:06 
GeneralRe: Custom FrameworkElement with child controls Pin
Kenneth Haugland13-Jan-16 1:39
mvaKenneth Haugland13-Jan-16 1:39 
GeneralRe: Custom FrameworkElement with child controls Pin
Gerry Schmitz13-Jan-16 6:25
mveGerry Schmitz13-Jan-16 6:25 
QuestionBinding a CompositeCollection to a Canvas (C#) Pin
Kenneth Haugland8-Jan-16 22:31
mvaKenneth Haugland8-Jan-16 22:31 
I have basically just copied the approach found here[^]. I just made some minor adjustments and wrapped the functionality inside a CustomControl:
C#
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;


public class MyCanvas : Canvas
{
    public static DependencyProperty ItemsSourceProperty =
        DependencyProperty.Register("ItemsSource",
        typeof(IEnumerable), typeof(MyCanvas),

        new FrameworkPropertyMetadata((IEnumerable)null,
            new PropertyChangedCallback(OnItemsSourcePropertyChanged)));

    private static Dictionary<INotifyCollectionChanged, MyCanvas> references = new Dictionary<INotifyCollectionChanged, MyCanvas>();

    public IEnumerable ItemsSource
    {
        get
        {
            return (IEnumerable)this.GetValue(ItemsSourceProperty);
        }
        set
        {
            this.SetValue(ItemsSourceProperty, value);
        }
    }

    private static void OnItemsSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var canvas = d as MyCanvas;
        repopulateChildren(canvas);


        if (canvas.ItemsSource is CompositeCollection)
        {
            CompositeCollection CollectionHolder = ((CompositeCollection)canvas.ItemsSource);

                foreach (CollectionContainer item in CollectionHolder)
            {

                ObservableCollection<UIElement> elements = (ObservableCollection<UIElement>)item.Collection;
                references.Add((elements as INotifyCollectionChanged), canvas);
                elements.CollectionChanged -= collectionChangedHandler;
                elements.CollectionChanged += collectionChangedHandler;
            }

        }
        else if (canvas.ItemsSource is IEnumerable<UIElement>)
        {
            var be = BindingOperations.GetBindingExpression(canvas, MyCanvas.ItemsSourceProperty);

            if (be != null)
            {
                var elements = (be.ResolvedSourcePropertyName == null ? be.ResolvedSource :
                    be.ResolvedSource.GetType().GetProperty(be.ResolvedSourcePropertyName).GetValue(be.ResolvedSource)) as INotifyCollectionChanged;

                if (elements != null)
                {
                    var cv = references.FirstOrDefault(i => i.Value == canvas);
                    if (!cv.Equals(default(KeyValuePair<INotifyCollectionChanged, MyCanvas>)))
                        references.Remove(cv.Key);


                    references[elements] = canvas;
                    elements.CollectionChanged -= collectionChangedHandler;
                    elements.CollectionChanged += collectionChangedHandler;
                }
            }
            else references.Clear();

        }

    }

    private static void collectionChangedHandler(object sender, NotifyCollectionChangedEventArgs e)
    {
        
        MyCanvas cv;

        if (references.TryGetValue(sender as INotifyCollectionChanged, out cv))
        {

            switch (e.Action)
        {
            case NotifyCollectionChangedAction.Add:
                foreach (var item in e.NewItems) cv.Children.Add(item as UIElement);
                break;
            case NotifyCollectionChangedAction.Remove:
                {
                    foreach (var item in e.OldItems)
                    {
                        cv.Children.Remove(item as UIElement);
                    }

                    break;
                }

            case NotifyCollectionChangedAction.Reset:
                repopulateChildren(cv);
                break;
        }
        }
    }


    public static DependencyProperty PerservedChildrenProperty = DependencyProperty.Register("PerservedChildren", typeof(int), typeof(MyCanvas), new PropertyMetadata(0));

    public int PerservedChildren
    {
        get
        {
            return (int)this.GetValue(PerservedChildrenProperty);
        }
        set
        {
            this.SetValue(PerservedChildrenProperty, value);
        }
    }

    private static void repopulateChildren(MyCanvas cv)
    {


        for (int i = cv.Children.Count - 1; i >= cv.PerservedChildren; i--)
        {
            cv.Children.RemoveAt(i);
        }

        var elements = (IEnumerable)cv.GetValue(ItemsSourceProperty );

        if (elements is CompositeCollection)
        {
            CompositeCollection CollectionHost = ((CompositeCollection)elements);
            foreach (CollectionContainer item in CollectionHost)
            {

                foreach (UIElement pp in item.Collection)
                {
                    if (!(cv.Children.Contains(pp)))
                        cv.Children.Add(pp);
                }
            }
        }
        else if (elements is IEnumerable<UIElement>)
        {
            foreach (UIElement elem in elements)
            {
                cv.Children.Add(elem);
            }
        }

    }

}


I can now bind an ObservableCollection<uielement> directly to the ItemsSource and it will work properly.

The problem appeared when I wanted to create support binding a CompositeCollection to it as well. The problem seems to be that I can't find the appropriate instance of the MyCanvas in the Dictionary, as it will only delete points found in one of the CollectionContainers bounded to the CompositeCollection. What am I missing here?

I did try and look at the ItemControl posted at Reference Source[^] since it seems to have support for CollectionContainers out of the box. I do realize that I can use an ItemControl to bind items to a canvas as well WPF Canvas, how to add children dynamically with MVVM code behind - Stack Overflow[^], and that could solve my problem, but I want to know how to make my code work with CollectionContainers.
AnswerRe: Binding a CompositeCollection to a Canvas (C#) Pin
Kenneth Haugland9-Jan-16 2:42
mvaKenneth Haugland9-Jan-16 2:42 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.