Skip to content

Instantly share code, notes, and snippets.

@mrtank
Last active September 20, 2016 13:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrtank/caaeeb25d7685c63780f2a8bfe8923fb to your computer and use it in GitHub Desktop.
Save mrtank/caaeeb25d7685c63780f2a8bfe8923fb to your computer and use it in GitHub Desktop.
// wiew
<TreeView Name="MyTree">
<TreeView.Resources>
<!-- would be nice, if it would be ILink for more extendability. Didn't work for some reason. Click and Children have to be added to ILink for that to work. In that case LinkViewModel should be implemented to have a clear short ILink -->
<HierarchicalDataTemplate DataType="{x:Type local:Link}" ItemsSource="{Binding Children}">
<StackPanel>
<Label Content="{Binding ElementName}"/>
<Button Command="{Binding Click}">Press to update</Button>
</StackPanel>
</HierarchicalDataTemplate>
<!-- would be nice, if it would be ICollectionInformation for more extendability. Didn't work for some reason.-->
<HierarchicalDataTemplate DataType="{x:Type local:CollectionInformation}" ItemsSource="{Binding ListOfChildren}">
<StackPanel>
<Label Content="{Binding ElementName}"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
// code
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
//MyTree.Items.Add(new Link(new CollectionInformation(new List<IElement>())));
MyTree.Items.Add(new CollectionInformation(new List<IElement> {new Link(new CollectionInformation(new List<IElement> {new Link(null)})) {ElementName = "My name"}, new Link(null)}));
}
}
// common interface. All node uses this.
public interface IElement
{
string ElementName { get; set; }
string ElementDescription { get; set; }
void DoUpdate(object arg);
}
public class Link : ILink
{
// IObs is constructor injected. Still I from SOLID
private readonly IObs _obs;
public Link(IElement referencedElement, IObs obs)
{
ReferencedElement = referencedElement;
_obs = obs;
Click = new RelayCommand(UpdateLink, _ => true);
}
public string ElementName { get; set; } = "Link";
public string ElementDescription { get; set; } = "It is a link";
public IElement ReferencedElement { get; }
// needed for WPF ItemsSource. We should not add this.
public List<IElement> Children
{
get { return new List<IElement> {ReferencedElement}; }
}
public ICommand Click { get; private set; }
public void UpdateLink(object arg)
{
// now comes the real question. What we expect of an IElement. Should it have DoUpdate, which propagates further
// or check the next step ourselfs
// ILink referencedElement = ReferencedElement as ILink;
// if (referencedElement != null)
// {
// referencedElement.UpdateLink(arg);
// }
// propagation through external observer
if (ReferencedElement == null)
return;
_obs.Notify(this, arg);
}
public void DoUpdate(object arg)
{
Console.WriteLine("I did stuff");
}
}
// I from SOLID. Link shows only the reachable property and method. User doesn't have to know about click, and other stuff.
public interface ILink : IElement
{
IElement ReferencedElement { get; }
void UpdateLink(object arg);
}
public class CollectionInformation : ICollectionInformation
{
public CollectionInformation(List<IElement> children)
{
ListOfChildren = children;
}
public List<IElement> ListOfChildren { get; }
public string ElementName { get; set; } = "Collection info";
public string ElementDescription { get; set; } = "desc";
public void DoUpdate(object arg)
{
Console.WriteLine("I did stuff");
}
}
// extended functionality type 2
public interface ICollectionInformation: IElement
{
List<IElement> ListOfChildren { get; }
}
// somewhere in an observer
// public void Notify(IElement self, object arg)
// {
// foreach (IElement element in ObservedElements)
// {
// if (self == element)
// continue;
// element.DoUpdate(arg);
// }
// }
// not related to question.
public class RelayCommand : ICommand
{
private Action<object> execute;
private Func<object, bool> canExecute;
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
{
this.execute = execute;
this.canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return this.canExecute == null || this.canExecute(parameter);
}
public void Execute(object parameter)
{
this.execute(parameter);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment