Im building a plugin system where each plugin has its own statusbar, containing different regions. So Plugin #1 could have a statusbar with 2 x 200 pixels regions, while Plugin #2 can have just a single 400 pixel region.
Im building this in WPF/MVVM
and in my viewmodel for the application, the StatusBar
for the plugin gets loaded when i switch between plugins.
I have a observablecollection of statusbars that i load to:
ObservableCollection<StatusBar> StatusBars
{
get;
set;
}
And then i have a function just retrieves the collection of statusbars for that plugin.
The class that gets loaded looks something like this:
public class StatusBar : ObservableObject
{
public string Name { get; set; }
public int Width { get; set; }
public StatusBarAreaType Type { get; set; }
string _message;
public string Message
{
get
{
return _message;
}
set
{
if (_message != value)
{
_message = value;
OnPropertyChanged();
}
}
}
}
My problem is that i cant get the XAML to support me loading the collection and showing each StatusBar
as its own region. A simplified version of how i tried going about this looks something like this:
<StatusBar VerticalAlignment="Bottom" Height="25" ItemsSource="{Binding StatusBars}" ItemTemplate="{DynamicResource StatusBarTemplate}">
<StatusBar.Resources>
<DataTemplate x:Key="StatusBarTemplate">
<TextBlock Text="{Binding Message}"></TextBlock>
</DataTemplate>
</StatusBar.Resources>
</StatusBar>
(I have tried StatusBarItem
stuff, ItemsControl
templates, using a grid inside instead etc etc)
How do i achieve my goal of having a StatusBar
consisting of different regions based on the StatusBar class?
I was actually able to resolve this now, here is my XAML:
<UserControl x:Class="MyCompany.View.StatusBarControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:viewModel="clr-namespace:MyCompany.ViewModel"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
DataContext="{Binding StatusBar,Source={StaticResource Locator}}">
<UserControl.Resources>
<DataTemplate x:Key="SimpleTextDataTemplate">
<StatusBarItem Width="{Binding Width}" Margin="0,5,0,0">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Message}"></TextBlock>
</StackPanel>
</StatusBarItem>
</DataTemplate>
<DataTemplate x:Key="ErrorDataTemplate">
<StatusBarItem Width="{Binding Width}" Margin="0,5,0,0">
<TextBlock Text="{Binding Message}"></TextBlock>
</StatusBarItem>
</DataTemplate>
<DataTemplate x:Key="ProgressBarDataTemplate">
<StatusBarItem Width="{Binding Width}" Margin="0,10,0,0">
<ProgressBar Width="{Binding Width}" Height="{Binding ElementName=theStatusBar,Path=Height}" Value="{Binding Message}"></ProgressBar>
</StatusBarItem>
</DataTemplate>
</UserControl.Resources>
<Grid>
<StatusBar x:Name="theStatusBar" VerticalAlignment="Bottom" Background="#d0d2d6" Height="30"
ItemsSource="{Binding StatusBars}">
<StatusBar.ItemTemplateSelector>
<viewModel:StatusBarRegionSelector SimpleTextTemplate="{StaticResource SimpleTextDataTemplate}"
ErrorTemplate="{StaticResource ErrorDataTemplate}"
ProgressBarTemplate="{StaticResource ProgressBarDataTemplate}" />
</StatusBar.ItemTemplateSelector>
</StatusBar>
</Grid>
</UserControl>
And the code behind:
public class StatusBarRegionSelector : DataTemplateSelector
{
public DataTemplate SimpleTextTemplate { get; set; }
public DataTemplate ErrorTemplate { get; set; }
public DataTemplate ProgressBarTemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var statusBar = (StatusBar) item;
if (statusBar != null)
switch (statusBar.Type)
{
case StatusBarAreaType.SimpleText:
return SimpleTextTemplate;
break;
case StatusBarAreaType.Error:
return ErrorTemplate;
break;
case StatusBarAreaType.ProgressBar:
return ProgressBarTemplate;
break;
default:
throw new ArgumentOutOfRangeException();
}
return SimpleTextTemplate;
}
}
Only issue left now is to add a seperator between each item, just adding a seperator right now does not work for some reason, it wont show up no matter where i place it.