Reputation: 355
I have a simple form that as a dynamic set of Parent Labels ( could be 1 -10 labels ) that is updated on a timer, if all is good these labels stay green like:
If however one of the parents has a status change, i am trying to then display the offending child or childs and result in somewthing like this:
then once status returns to normal revert back to the original layout ( as above )
so currently i have a view like this :
<Grid>
<ItemsControl ItemsSource = "{Binding Path = CIs}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Label Content = "{Binding Path = NodeName, Mode = OneWay}"
Background = "{Binding Path = NodeStatus, Mode = OneWay}"
Tag="{Binding Path = Nodeid, Mode = OneWay}"
Foreground="White"
FontFamily="Arial Black"
HorizontalContentAlignment="Center"
BorderBrush="Black"
BorderThickness="1,1,1,1"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
a viewmodel populating the view with a simple add:
if (Node.level == 3)
{
CIs.Add(new CI { NodeName = Node.name, NodeStatus = Node.status, Nodeid = Node.id });
}
and the basic model :
public class CIModel {}
public class CI : INotifyPropertyChanged {
private string nodeName;
private string nodeStatus;
private string nodeid;
public string NodeName {
get {
return nodeName;
}
set {
if (nodeName != value) {
nodeName = value;
RaisePropertyChanged("NodeName");
}
}
}
public string Nodeid
{
get
{
return nodeid;
}
set
{
if (nodeid != value)
{
nodeid = value;
RaisePropertyChanged("Nodeid");
}
}
}
public string NodeStatus
{
get
{
return nodeStatus;
}
set
{
if (nodeStatus != value)
{
nodeStatus = value;
RaisePropertyChanged("NodeStatus");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string property) {
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
would creating a child view somehow on the parent status change be a possible way? or can i create all the parent and childs and toggle there visibility when there status changes?
Thanks
Upvotes: 0
Views: 229
Reputation: 1357
Did you mean something like this?
// Put this in MainWindow()
public MainWindow()
{
InitializeComponent();
new Demo(this);
}
// Demo code
public class Demo
{
public Demo(FrameworkElement view)
{
View = view;
View.DataContext = this;
StartDemo();
}
private FrameworkElement View { get; }
public ObservableCollection<Parent> Parents { get; } = new ObservableCollection<Parent>();
public async void StartDemo()
{
var delay = 500;
foreach (var index in Enumerable.Range(0, 5))
{
var item = new Parent { Name = $"Parent {index + 1}" };
Parents.Add(item);
await Task.Delay(delay);
}
// Add errors
for (var i = 0; i < 3; i++)
{
Parents[1].Errors.Add(new Child { Name = $"Child {i + 1}" });
await Task.Delay(delay);
}
// Remove errors
while (Parents[1].Errors.Any())
{
Parents[1].Errors.RemoveAt(Parents[1].Errors.Count - 1);
await Task.Delay(delay);
}
// Remove parents
while (Parents.Any())
{
Parents.RemoveAt(Parents.Count-1);
await Task.Delay(delay);
}
}
}
/// <summary>
/// Child (error item)
/// </summary>
public class Child
{
public string Name { get; set; }
}
/// <summary>
/// Parent
/// </summary>
public class Parent : INotifyPropertyChanged
{
public Parent()
{
System.Collections.Specialized.CollectionChangedEventManager.AddHandler(Errors,
delegate
{
OnPropertyChanged(nameof(Status));
});
}
private string _name;
public string Name
{
get { return _name; }
set { _name = value; OnPropertyChanged(); }
}
public string Status { get { return Errors.Any() ? "ERROR" : "OK"; } }
/// <summary>
/// Children/errors
/// </summary>
public ObservableCollection<Child> Errors { get; } = new ObservableCollection<Child>();
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
<!-- Xaml -->
<ItemsControl ItemsSource="{Binding Path=Parents}"
Grid.IsSharedSizeScope="True">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type local:Parent}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="ParentColumn" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<!-- Parent label -->
<Label Content="{Binding Path=Name}"
x:Name="Label"/>
<!-- Errors -->
<ItemsControl ItemsSource="{Binding Path=Errors}"
Grid.Column="1">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type local:Child}">
<Label Content="{Binding Path=Name}"
Background="Red" />
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Grid>
<DataTemplate.Triggers>
<!-- Parent is ok -->
<DataTrigger Binding="{Binding Path=Status}"
Value="OK">
<Setter TargetName="Label" Property="Background" Value="Green" />
</DataTrigger>
<!-- Parent is not ok -->
<DataTrigger Binding="{Binding Path=Status}"
Value="ERROR">
<Setter TargetName="Label" Property="Background" Value="Red" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Upvotes: 1