[WPF] XAML how to inherit lists?

FireFenix 21 Reputation points
2020-04-08T20:58:35.07+00:00

Hello everyone!

I have a structure

class MyContainer
{
    List<MyItem> Items;
}

class MyItem
{
    string Name;
    int Value;
}

I want to get instances of Containers whic have values from the base => mean broadcast values to other containers to reduce item definitioan

my imagination

<MyContainer x:Key="DefaultCase">
    <MyItem Name="Four" Value="1"/>
    <MyItem Name="Four" Value="2"/>
</MyContainer>

<MyContainer x:Key="FirstCase" Template="DefaultCase">
    <MyItem Name="Three" Value="3"/>
</MyContainer>

<MyContainer x:Key="SecondCase" Template="DefaultCase">
    <MyItem Name="Four" Value="4"/>
</MyContainer>

To fill containers of List type alike

List<MyItem> DefaultCase
1
2

List<MyItem> FirstCase
1
2
3

List<MyItem> SecondCase
1
2
4

Can somebody help me?

Ofc I know that I can do it from code but I want use xaml for configuration with List type.

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,667 questions
0 comments No comments
{count} votes

Accepted answer
  1. Peter Fleischer (former MVP) 19,231 Reputation points
    2020-04-09T09:30:11.32+00:00

    Hi, you can write your own "combined list" like in following console demo:

    using System;
    using System.Collections;
    using System.Collections.Generic;
    
    namespace ConsoleApp1
    {
      class Program25
      {
        static void Main(string[] args)
        {
          try
          {
            (new Demo()).Execute();
          }
          catch (Exception ex) { Console.WriteLine(ex.ToString()); }
          Console.WriteLine("Continue enter key");
          Console.ReadKey();
        }
    
        internal class Demo
        {
          internal void Execute()
          {
            List<MyItem> list1 = new List<MyItem>();
            list1.Add(new MyItem() { Name = "Four", Value = 1 });
            list1.Add(new MyItem() { Name = "Four", Value = 2 });
    
            CombinedList<MyItem> list2 = new CombinedList<MyItem>(list1);
            list2.Add(new MyItem() { Name = "Four", Value = 3 });
    
            CombinedList<MyItem> list3 = new CombinedList<MyItem>(list1);
            list3.Add(new MyItem() { Name = "Four", Value = 4 });
    
            Console.WriteLine("--- combined list2");
            foreach (var item in list2) Console.WriteLine($"{item.Name}, Value: {item.Value}");
    
            Console.WriteLine("--- combined list3");
            foreach (var item in list3) Console.WriteLine($"{item.Name}, Value: {item.Value}");
          }
        }
    
        public class CombinedList<T> : IList<T>, ICollection<T>, IEnumerable<T>, IEnumerable, IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>
        {
          public CombinedList(List<T> primary)
          {
            externList = primary;
          }
    
          private List<T> externList;
          private List<T> internList = new List<T>();
    
          public T this[int index] { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
    
          public int Count => throw new NotImplementedException();
    
          public bool IsReadOnly => throw new NotImplementedException();
    
          public bool IsFixedSize => throw new NotImplementedException();
    
          public object SyncRoot => throw new NotImplementedException();
    
          public bool IsSynchronized => throw new NotImplementedException();
    
          object IList.this[int index] { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
    
          public void Add(T item)
          {
            internList.Add(item);
          }
    
          public void Clear()
          {
            throw new NotImplementedException();
          }
    
          public bool Contains(T item)
          {
            throw new NotImplementedException();
          }
    
          public void CopyTo(T[] array, int arrayIndex)
          {
            throw new NotImplementedException();
          }
    
          public IEnumerator<T> GetEnumerator()
          {
            return new CombinedEnumerator<T>(externList, internList);
          }
    
          public int IndexOf(T item)
          {
            throw new NotImplementedException();
          }
    
          public void Insert(int index, T item)
          {
            throw new NotImplementedException();
          }
    
          public bool Remove(T item)
          {
            throw new NotImplementedException();
          }
    
          public void RemoveAt(int index)
          {
            throw new NotImplementedException();
          }
    
          IEnumerator IEnumerable.GetEnumerator()
          {
            throw new NotImplementedException();
          }
    
          public int Add(object value)
          {
            throw new NotImplementedException();
          }
    
          public bool Contains(object value)
          {
            throw new NotImplementedException();
          }
    
          public int IndexOf(object value)
          {
            throw new NotImplementedException();
          }
    
          public void Insert(int index, object value)
          {
            throw new NotImplementedException();
          }
    
          public void Remove(object value)
          {
            throw new NotImplementedException();
          }
    
          public void CopyTo(Array array, int index)
          {
            throw new NotImplementedException();
          }
    
          public class CombinedEnumerator<U> : IEnumerator<U>
          {
            public CombinedEnumerator(List<U> externList, List<U> internList)
            {
              this.externList = externList;
              this.internList = internList;
            }
    
            private List<U> externList;
            private List<U> internList;
            private int i = -1;
    
            public U Current => (i < externList.Count) ? externList[i] : internList[i - externList.Count];
    
            object IEnumerator.Current => throw new NotImplementedException();
    
            public void Dispose() { }
    
            public bool MoveNext()
            {
              i++;
              return i < internList.Count + externList.Count;
            }
    
            public void Reset() => i = -1;
          }
        }
        public class MyItem
        {
          public string Name;
          public int Value;
        }
      }
    }
    
    1 person found this answer helpful.
    0 comments No comments

3 additional answers

Sort by: Most helpful
  1. gekka 6,436 Reputation points MVP
    2020-04-09T03:54:46.767+00:00

    Hi FireFenix,

    If you only want to use Xaml, merge with CompositeCollection.

    <UniformGrid>
        <UniformGrid.Resources>
            <DataTemplate DataType="{x:Type local:MyItem}">
                <TextBlock>
                    <Run Text="{Binding Path=Name,Mode=OneWay}" Foreground="Blue"/>
                    <Run Text="{Binding Path=Value,Mode=OneWay}" Foreground="Red"/>
                </TextBlock>
            </DataTemplate>
        </UniformGrid.Resources>
    
        <ListBox x:Name="DefaultCase" >
            <local:MyItem Name="One" Value="1"/>
            <local:MyItem Name="Two" Value="2"/>
        </ListBox>
    
        <ListBox SelectedItem="{Binding ElementName=DefaultCase,Path=SelectedItem,Mode=TwoWay}">
            <ItemsControl.ItemsSource>
                <CompositeCollection>
                    <CollectionContainer Collection="{Binding Path=Items,Source={x:Reference Name=DefaultCase}}"/>
                    <CollectionContainer >
                        <CollectionContainer.Collection>
                            <x:Array Type="{x:Type local:MyItem}">
                                <local:MyItem Name="Three" Value="3"/>
                            </x:Array>
                        </CollectionContainer.Collection>
                    </CollectionContainer>
                </CompositeCollection>
            </ItemsControl.ItemsSource>
        </ListBox>
    
    </UniformGrid>
    
    0 comments No comments

  2. FireFenix 21 Reputation points
    2020-04-09T07:53:24.257+00:00

    If you only want to use Xaml, merge with CompositeCollection.

    I saw that class but it's working only for a ItemsSource at container controls.
    And it's not working on List datatype :(

    0 comments No comments

  3. FireFenix 21 Reputation points
    2020-04-09T12:54:24.763+00:00

    Hmm..... Interesting, I'll try.
    Thanks.

    0 comments No comments