How To Style Modern UI RadialGaugeChart - c#

I'm using Modern UI Charts in my project (Modern UI Charts), and I'm trying to change the chart foreground and palette based on ValueMember.
I have a converter:
public class MetricsColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
//Dim num As Integer
string color = null;
decimal intValue = default(decimal);
if (decimal.TryParse(value.ToString(), intValue)) {
if (intValue <= 60.0) {
return "Red";
} else if (intValue >= 60.01 && intValue < 80.0) {
return "Yellow";
} else if (intValue >= 80.01) {
return "Green";
}
}
return color;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
And my xaml with a chart:
<chart:RadialGaugeChart
ChartTitleVisibility="Collapsed"
ChartLegendVisibility="Collapsed"
ToolTipFormat="{}Caption: {0}, Value: '{1}', Series: '{2}', Percentage: {3:P2}"
HorizontalAlignment="Left" VerticalAlignment="Top" Margin="5,5,5,5" Height="170" >
<chart:RadialGaugeChart.Style>
<Style TargetType="{x:Type chart:RadialGaugeChart}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ProductivitySeries, Path=ValueMember, Converter={StaticResource MetricsConverter}}" Value="Green">
<Setter Property="Foreground" Value="{StaticResource Flat_GreenAccentBrush}"/>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=ProductivitySeries, Path=ValueMember, Converter={StaticResource MetricsConverter}} "Value="Yellow">
<Setter Property="Foreground" Value="{StaticResource Flat_MetricYellowBrush}"/>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=ProductivitySeries, Path=ValueMember, Converter={StaticResource MetricsConverter}}" Value="Red">
<Setter Property="Foreground" Value="{StaticResource Flat_MetricRedBrush}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</chart:RadialGaugeChart.Style>
<chart:RadialGaugeChart.Series>
<chart:ChartSeries
Name="ProductivitySeries"
SeriesTitle="Productivity"
ItemsSource="{Binding TeamLeaderViewM.TeamLeaderMetrics}"
DisplayMember="TeamLeader"
ValueMember="Productivity"/>
</chart:RadialGaugeChart.Series>
</chart:RadialGaugeChart>
Unfortunately, nothing is changing here. Color is the same, all the time.
How can I implement this to my charts?
Thank you for suuggestions

You have to modify the default PlotterArea style as shown below:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
xmlns:MetroChart="clr-namespace:De.TorstenMandelkow.MetroChart;assembly=De.TorstenMandelkow.MetroChart"
x:Class="WpfApplication1.MainWindow"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/De.TorstenMandelkow.MetroChart;component/Themes/Generic.xaml"/>
</ResourceDictionary.MergedDictionaries>
<local:MetricsColorConverter x:Key="Converter1"></local:MetricsColorConverter>
<x:Array x:Key="SampleData1" Type="{x:Type local:MyData}">
<local:MyData TeamLeader="Team A" Productivity="50"></local:MyData>
<local:MyData TeamLeader="Team B" Productivity="75"></local:MyData>
<local:MyData TeamLeader="Team C" Productivity="90"></local:MyData>
</x:Array>
<Style x:Key="RadialGaugeChartPlotterAreaStyle1" TargetType="MetroChart:PlotterArea">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="MetroChart:PlotterArea">
<MetroChart:FadingListView Style="{StaticResource FadingListViewStyle}" ItemsSource="{Binding Path=ParentChart.DataPointGroups, RelativeSource={RelativeSource Mode=TemplatedParent}}">
<MetroChart:FadingListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</MetroChart:FadingListView.ItemsPanel>
<MetroChart:FadingListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border Grid.Row="0" Visibility="{Binding Path=ShowCaption, Converter={StaticResource BooleanToVisibilityConverter}}">
<TextBlock Text="{Binding Path=Caption}" Style="{StaticResource SeriesTitleStyle}" />
</Border>
<MetroChart:FadingListView Style="{StaticResource FadingListViewStyle}"
x:Name="itemsControl"
ItemsSource="{Binding Path=DataPoints}"
Margin="5"
Grid.Row="1">
<MetroChart:FadingListView.ItemsPanel>
<ItemsPanelTemplate>
<!--<StackPanel Orientation="Horizontal" />-->
<MetroChart:UniformGridPanel Orientation="Horizontal" MinimalGridWidth="150.0" />
</ItemsPanelTemplate>
</MetroChart:FadingListView.ItemsPanel>
<MetroChart:FadingListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<MetroChart:RadialGaugePiece
Grid.Row="0"
Margin="5"
Background="{Binding Path=Value, Converter={StaticResource Converter1}}"
SelectedBrush="{Binding Path=SelectedBrush}"
Value="{Binding Path=Value}"
IsClickedByUser="{Binding Path=IsClickedByUser, Mode=TwoWay}"
IsSelected="{Binding Path=IsSelected}"
ClientWidth="180"
ClientHeight="180"
x:Name="radial">
</MetroChart:RadialGaugePiece>
<Border Grid.Row="1" HorizontalAlignment="Center" Margin="0 0 0 10">
<TextBlock Text="{Binding Path=SeriesCaption}" />
</Border>
</Grid>
</DataTemplate>
</MetroChart:FadingListView.ItemTemplate>
</MetroChart:FadingListView>
</Grid>
</DataTemplate>
</MetroChart:FadingListView.ItemTemplate>
</MetroChart:FadingListView>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</Window.Resources>
<Grid>
<MetroChart:RadialGaugeChart ChartTitle="My Sample"
ChartSubTitle="Productivity"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
PlotterAreaStyle="{StaticResource RadialGaugeChartPlotterAreaStyle1}">
<MetroChart:RadialGaugeChart.Series>
<MetroChart:ChartSeries Name="ProductivitySeries"
SeriesTitle="My Series"
DisplayMember="TeamLeader"
ValueMember="Productivity"
ItemsSource="{StaticResource SampleData1}" />
</MetroChart:RadialGaugeChart.Series>
</MetroChart:RadialGaugeChart>
</Grid>

Related

LiveCharts ColumnSeries not showing

I'm using LiveCharts in WPF to visualize the results of some analyses. The results of an analysis is added to a SeriesCollection and displayed in an CartesianChart. You can choose which type of series to use: LineSeries or ColumnSeries. The chosen type is then created and added to the SeriesCollection.
There's a custom mapper for selecting X and Y values from the ChartValues and a AxisFormatter for the X axis.
The charts are part of an Blacklight.Controls.Wpf.DragDockPanelHost. Each chart is an DragDockPanel with a style attached to it. The chart itself is a ContentControl with an TemplateSelector that returns the CartesianChart-XAML as a DataTemplate.
I've already tried to set the Fill or Stroke of the series or putting some ColumnSeries in there manually but that didn't help at all.
Filling of the SeriesCollection:
private SeriesCollection _Series;
public SeriesCollection Series
{
get { return _Series; }
set { SetProperty<SeriesCollection>(ref _Series, value); }
}
...
private void createDiagram()
{
if (this._Analysis!= null && this._Diagram != null)
{
this.Series.Clear();
foreach (KeyValuePair<state, Dictionary<DateTime, int>> kvp in this.Analysis.Execute())
{
Series series = Activator.CreateInstance(Diagram) as Series;
if (series != null)
{
series.Title = kvp.Key.name;
series.Values = new ChartValues<KeyValuePair<DateTime, int>>(kvp.Value);
this.Serien.Add(series);
}
}
}
}
Mapper and AxisFormatter:
CartesianMapper<KeyValuePair<DateTime, int>> mapper = Mappers.Xy<KeyValuePair<DateTime, int>>().X(kvp => ((DateTimeOffset)kvp.Key).ToUnixTimeSeconds()).Y(kvp => kvp.Value);
this.Series = new SeriesCollection(mapper);
this.XFormatter = value =>
{
return DateTimeOffset.FromUnixTimeSeconds((long)value).DateTime.ToString("dd.MM.yyyy HH:mm");
};
TemplateSelector:
public class DashboardElementTemplateSelector : DataTemplateSelector
{
public DataTemplate ListDashboardElementTemplate { get; set; }
public DataTemplate SingleValueDashboardElementTemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item is ListDashboardElementViewModel)
return this.ListDashboardElementTemplate;
else
return this.SingleValueDashboardElementTemplate;
}
}
XAML of DragDockPanelHost:
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<DataTemplate x:Key="listElement">
<views:ListDashboardElementView/>
</DataTemplate>
<DataTemplate x:Key="singleValueElement">
<views:SingleValueDashboardElementView/>
</DataTemplate>
<tempselect:DashboardElementTemplateSelector x:Key="elementTempSelector"
ListDashboardElementTemplate="{StaticResource listElement}"
SingleValueDashboardElementTemplate="{StaticResource singleValueElement}"
/>
</ResourceDictionary>
<ResourceDictionary>
<conv:BooleanToVisibilityConverter x:Key="visCon"/>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<bl:DragDockPanelHost ItemsSource="{Binding Diagrams}" Grid.Row="1" Margin="20" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<bl:DragDockPanelHost.Style>
<Style TargetType="bl:DragDockPanelHost">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<Canvas ClipToBounds="True" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
</Canvas>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="bl:DragDockPanelHost">
<ItemsPresenter/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</bl:DragDockPanelHost.Style>
<bl:DragDockPanelHost.DefaultPanelStyle>
<Style TargetType="{x:Type bl:DragDockPanel}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid Margin="10">
<Grid Margin="5">
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border Background="#00000000" Margin="-2" Padding="5" Grid.Row="0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<WrapPanel>
<Image Width="20" x:Name="GripBarElement" Source="/Aisys.XStorage.Dashboard;component/Images/move.png" Grid.Column="0" Cursor="Hand" HorizontalAlignment="Left"/>
<TextBlock Text="{Binding Name}" Grid.Column="0" FontSize="16" FontWeight="Bold" Margin="10,0,0,0"/>
</WrapPanel>
<WrapPanel HorizontalAlignment="Right" Grid.Column="2">
<Button Command="{Binding ExecuteCommand}" CommandParameter="{Binding}" Margin="5,0,5,0">
<Button.Template>
<ControlTemplate>
<Image Source="/Aisys.XStorage.Dashboard;component/Images/Refresh.png"/>
</ControlTemplate>
</Button.Template>
</Button>
<Button Width="20" Command="{Binding DataContext.RemoveDiagramCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type bl:DragDockPanelHost}}}" CommandParameter="{Binding}">
<Button.Template>
<ControlTemplate>
<Image Source="/Aisys.XStorage.Dashboard;component/Images/Remove.png"/>
</ControlTemplate>
</Button.Template>
</Button>
<Button Command="{Binding DataContext.ShowPropertiesCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type bl:DragDockPanelHost}}}" CommandParameter="{Binding}" Margin="5,0,5,0">
<Button.Template>
<ControlTemplate>
<Image Source="/Aisys.XStorage.Dashboard;component/Images/Preferences.png"/>
</ControlTemplate>
</Button.Template>
</Button>
<ToggleButton x:Name="MaximizeToggleButton" VerticalAlignment="Top" HorizontalAlignment="Right" IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay, Path=IsMaximized}" Margin="0,5,5,0" Width="25" Height="25" Cursor="Hand">
<ToggleButton.Template>
<ControlTemplate TargetType="ToggleButton">
<Image Source="/Aisys.XStorage.Dashboard;component/Images/Maximize.png" Margin="0,0,0,5"/>
</ControlTemplate>
</ToggleButton.Template>
</ToggleButton>
</WrapPanel>
</Grid>
</Border>
<Separator VerticalAlignment="Bottom" Margin="0,0,0,0"/>
<ContentControl Content="{Binding}" ContentTemplateSelector="{StaticResource elementTempSelector}" Grid.Row="1" Margin="10"/>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</bl:DragDockPanelHost.DefaultPanelStyle>
</bl:DragDockPanelHost>
XAML of chart:
<Grid>
<lvc:CartesianChart Series="{Binding Series}" LegendLocation="Right" Name="chart">
<lvc:CartesianChart.AxisX>
<lvc:Axis Title="Zeit" LabelFormatter="{Binding XFormatter}">
</lvc:Axis>
</lvc:CartesianChart.AxisX>
</lvc:CartesianChart>
</Grid>
If I'm choosing LineSeries, everything works fine. But when I'm using ColumnSeries nothing is shown. You can see, that the axis is redrawn and the separators move. The legend is also drawn, but there are no columns visible.
Any ideas why this is happening?
I had the same problem recently. Unfortunately, this doesn't seem to be documented anywhere but for some reason if you have too many data points for the size of the graph, then none of the columns will display. You can either try reducing the number of data points until it works (in my case 90 data points wouldn't display, but 30 would), or on ColumnSeries there is a property ColumnPadding that you can turn down to zero and see if that helps.

Converter returns value, but nothing happens

I'm trying to bind custom textbox's BorderBrush/Foreground to its Text
The TextToBrush converter is called on Text change and the correct Brush is returned, but the actual foreground remains black and the actual border is not visible at all.
What am I doing wrong?
TextBox Style:
<Style TargetType="TextBox" x:Key="ScaleInputStyle">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="2*"/>
<RowDefinition Height="5*"/>
<RowDefinition Height="5*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="6*"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.Background>
<ImageBrush ImageSource="{StaticResource ResourceKey=ScaleBgnd}" />
</Grid.Background>
<Border x:Name="InputBorder"
Grid.Row="1" Grid.Column="1"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="5"
BorderBrush="{TemplateBinding BorderBrush}">
<TextBox x:Name="Input"
Text="{TemplateBinding Text}"
MaxLength="4"
BorderThickness="0"
BorderBrush="{x:Null}"
Foreground="{TemplateBinding Foreground}"
FontSize="40"
TextAlignment="Center"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Background="Transparent" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
TextBox:
<TextBox x:Name="ScaleInput"
Text="{Binding ElementName=PhotoDisplay, Path=PhotoImage.ScaleSize, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource TxtBoxToDoubleAndBack}}"
Style="{StaticResource ScaleInputStyle}"
Grid.Column="3" Grid.Row="4"
Foreground="{Binding Text, RelativeSource={RelativeSource Self}, Converter={StaticResource TextToBrush}, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True, NotifyOnTargetUpdated=True}"
Width="{Binding ActualHeight, RelativeSource={RelativeSource Self}}"
BorderBrush="{Binding Text, RelativeSource={RelativeSource Self}, Converter={StaticResource TextToBrush}, UpdateSourceTrigger=PropertyChanged, NotifyOnSourceUpdated=True, NotifyOnTargetUpdated=True}"
BorderThickness="3"
IsEnabled="{Binding Path=ActionMode, ElementName=PhotoDisplay, Converter={StaticResource ActionToEnable}, ConverterParameter=EnableOnEvaluate, UpdateSourceTrigger=PropertyChanged}" />
Converter:
public class ConvertTextToBrush : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
{
return Brushes.OrangeRed;
}
return Regex.IsMatch(value.ToString(), #"^((\d{1,2})(.\d)?)$", RegexOptions.IgnoreCase | RegexOptions.Singleline)
? Brushes.DodgerBlue
: Brushes.OrangeRed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

Resize the window based on the content

I tried different things but without success
I have to size the window relative to the dynamic numbers of tiles (MahApps.Metro) but only in height, once the height exceeded of my screen I put a scroolbar
In my window I have for the moment:
<Controls:MetroWindow x:Class="EpiTUILE.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
Title="EpiTUILE" Height="270" Width="400" ShowMaxRestoreButton="False" ShowCloseButton="False"
Top="0" Loaded="MetroWindow_Loaded" Icon="Alerte.png" Closing="MetroWindow_Closing"
MouseMove="MetroWindow_MouseMove" ResizeMode="CanMinimize" MouseEnter="MetroWindow_MouseEnter"
StateChanged="MetroWindow_StateChanged" WindowStyle="None" UseLayoutRounding="True"
AllowsTransparency="True" Background="Transparent" WindowState="Minimized">
<Window.Resources>
<Style x:Key="TileStyle" TargetType="Controls:Tile">
<EventSetter Event="PreviewMouseDown" Handler="OnTileClick" />
<Setter Property="Width" Value="380" />
<Setter Property="Height" Value="70" />
<Setter Property="TitleFontSize" Value="10" />
</Style>
</Window.Resources>
<Grid Height="Auto">
<ScrollViewer x:Name="MyScrollViewer" VerticalScrollBarVisibility="Auto" Grid.Row="1" Width="Auto" Height="Auto" Grid.ColumnSpan="2" ScrollViewer.FlowDirection="LeftToRight" >
<WrapPanel Name="PanelTile" Orientation="Vertical" HorizontalAlignment="Center" Height="Auto" >
</WrapPanel>
</ScrollViewer>
</Grid>
I then build my tiles in code behind:
PanelTile.Children.Clear();
for (int i = 0; i < _nbrTile; i++)
{
Tile _tile = new Tile();
_tile.HorizontalTitleAlignment = HorizontalAlignment.Right;
_tile.Title = i.ToString();
_tile.Style = this.FindResource("TileStyle") as Style;
_tile.Content = "Type Alerte " + i;
PanelTile.Children.Add(_tile);
}

SelectedItems from nested listview

I am developing a Windows Store App in which I have a nested listview i.e. expandable listview. To retain the selected items in child listview I have used
<ListView Name="FiltersListview" ItemContainerStyle="{StaticResource StretchItemStyle}" SelectionChanged="FiltersListview_SelectionChanged" IsItemClickEnabled="True" ItemClick="FiltersListview_ItemClick" Grid.Row="1" Grid.ColumnSpan="2">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Interactivity:Interaction.Behaviors>
<Core:DataTriggerBehavior Binding="{Binding IsSelected}" Value="True">
<Core:ChangePropertyAction TargetObject="{Binding ElementName=view1}" PropertyName="Visibility" Value="Collapsed"/>
<Core:ChangePropertyAction TargetObject="{Binding ElementName=view2}" PropertyName="Visibility" Value="Visible"/>
</Core:DataTriggerBehavior>
<Core:DataTriggerBehavior Binding="{Binding IsSelected}" Value="False">
<Core:ChangePropertyAction TargetObject="{Binding ElementName=view1}" PropertyName="Visibility" Value="Visible"/>
<Core:ChangePropertyAction TargetObject="{Binding ElementName=view2}" PropertyName="Visibility" Value="Collapsed"/>
</Core:DataTriggerBehavior>
</Interactivity:Interaction.Behaviors>
<Grid Height="50" x:Name="view1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}" VerticalAlignment="Center" Style="{StaticResource PageTextStyle}"/>
<Image Margin="10" Grid.Column="1" Source="/Images/arrow-down.png"/>
<Rectangle Fill="Black" VerticalAlignment="Bottom" Height="1" Grid.ColumnSpan="2"/>
</Grid>
<Grid x:Name="view2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="{Binding Name}" VerticalAlignment="Center" Style="{StaticResource PageTextStyle}"/>
<Image Margin="10" Grid.Column="1" Source="/Images/arrow-up.png"/>
<ListView Margin="20,0" Grid.Row="1" RequestedTheme="Light" Grid.ColumnSpan="2" ItemsSource="{Binding SubList}" SelectionMode="Multiple">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="FontSize" Value="22"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Foreground" Value="Black"/>
</Style>
</ListView.ItemContainerStyle>
</ListView>
</Grid>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
and in code behind
private void FiltersListview_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
try
{
var item = (sender as ListView).SelectedItem as FilterM;
if (item != null)
item.IsSelected = true;
if (e.RemovedItems.Count > 0)
{
foreach (var Nitem in e.RemovedItems)
{
(Nitem as FilterM).IsSelected = false;
}
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
private void FiltersListview_ItemClick(object sender, ItemClickEventArgs e)
{
try
{
if ((sender as ListView).SelectedItem != null)
{
if ((sender as ListView).SelectedItem.Equals(e.ClickedItem))
(sender as ListView).SelectedItem = null;
else
(sender as ListView).SelectedItem = e.ClickedItem;
}
else
(sender as ListView).SelectedItem = e.ClickedItem;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
I have changed this question after my old question about it from here.
But now on tap of a button named Go I want to know all the selected items in child listviews of each item. I have stumbled upon links like this but I'm not using MVVM and unable to make it work in my case.
Can anybody help?
Well I have come up with a work around for this problem. I'm putting my solution if anybody needs it.
I have passed the child listview as parameter to ViewModel and managed it with help of command.
<ListView ItemContainerStyle="{StaticResource StretchItemStyle}" SelectionChanged="FiltersListview_SelectionChanged" IsItemClickEnabled="True" ItemClick="FiltersListview_ItemClick" Grid.Row="1" Grid.ColumnSpan="2" Margin="-1,0,1,44" Grid.RowSpan="2">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Interactivity:Interaction.Behaviors>
<Core:DataTriggerBehavior Binding="{Binding IsSelected}" Value="True">
<Core:ChangePropertyAction TargetObject="{Binding ElementName=view1}" PropertyName="Visibility" Value="Collapsed"/>
<Core:ChangePropertyAction TargetObject="{Binding ElementName=view2}" PropertyName="Visibility" Value="Visible"/>
</Core:DataTriggerBehavior>
<Core:DataTriggerBehavior Binding="{Binding IsSelected}" Value="False">
<Core:ChangePropertyAction TargetObject="{Binding ElementName=view1}" PropertyName="Visibility" Value="Visible"/>
<Core:ChangePropertyAction TargetObject="{Binding ElementName=view2}" PropertyName="Visibility" Value="Collapsed"/>
</Core:DataTriggerBehavior>
</Interactivity:Interaction.Behaviors>
<Grid Height="50" x:Name="view1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}" VerticalAlignment="Center" Style="{StaticResource PageTextStyle}"/>
<Image Margin="10" Grid.Column="1" Source="/Images/arrow-down.png"/>
<Rectangle Fill="Black" VerticalAlignment="Bottom" Height="1" Grid.ColumnSpan="2"/>
</Grid>
<Grid x:Name="view2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="{Binding Name}" VerticalAlignment="Center" Style="{StaticResource PageTextStyle}"/>
<Image Margin="10" Grid.Column="1" Source="/Images/arrow-up.png"/>
<ListView x:Name="SubListview" Margin="20,0" Grid.Row="1" RequestedTheme="Light" Grid.ColumnSpan="2" ItemsSource="{Binding SubList}" SelectionMode="Multiple">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="FontSize" Value="22"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Foreground" Value="Black"/>
</Style>
</ListView.ItemContainerStyle>
<Interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="SelectionChanged">
<Core:InvokeCommandAction Command="{Binding SelectionChangedCommand}" CommandParameter="{Binding ElementName=SubListview}"/>
<!--<Core:InvokeCommandAction Command="{Binding SelectionChangedCommand}" InputConverter="{StaticResource SelectionChangedConverter}" InputConverterParameter="{Binding ElementName=SubListview}"/>-->
</Core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</ListView>
<Rectangle Grid.Row="1" Fill="Black" VerticalAlignment="Bottom" Height="1" Grid.ColumnSpan="2"/>
</Grid>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
and in code behind
public class FilterM
{
public RelayCommand<IList<object>> SelectionChangedCommand
{
get
{
if (selectionChangedCommand == null)
{
selectionChangedCommand = new RelayCommand<IList<object>>(
items =>
{
// do something with selected items!
}
);
}
return selectionChangedCommand;
}
}
}
and set itemssource of First listview. I got this idea from this link. Hope it helps somebody like me.

WPF GroupStyle only for Groups with more than 1 item

I am trying to show different Groups in a Listview which contain an expander and a header. However I don't want my SecondLevel Group to show a header if the Group only contains 1 item.
Since this would be quite inconvenient.
My Code:
<Window x:Class="ListViewGrouping.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:listViewGrouping="clr-namespace:ListViewGrouping"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<listViewGrouping:GroupItemStyleSelector x:Key="groupItemStyleSelector"/>
<!-- Style for the first level GroupItem -->
<Style x:Key="FirstLevel" TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander IsExpanded="True">
<Expander.Header>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Margin="3.5,0" Text="{Binding Name}" TextBlock.FontWeight="Bold"/>
<TextBlock Grid.Column="1" Margin="3.5,0" Text="Elements:"/>
<TextBlock Grid.Column="2" Margin="3.5,0" Text="{Binding ItemCount}"/>
</Grid>
</Expander.Header>
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Style for the second level GroupItem -->
<Style x:Key="SecondLevel" TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander IsExpanded="True" Margin="15,0,0,0">
<Expander.Header>
<TextBlock Text="{Binding Name}" TextBlock.FontWeight="Bold"/>
</Expander.Header>
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<ListView Name="mailView" ItemsSource="{Binding}">
<ListView.GroupStyle>
<GroupStyle ContainerStyleSelector="{StaticResource groupItemStyleSelector}" />
</ListView.GroupStyle>
<ListView.View>
<GridView>
<GridViewColumn Header="ID" DisplayMemberBinding="{Binding ID}"/>
<GridViewColumn Header="Subject" DisplayMemberBinding="{Binding Subject}"/>
<GridViewColumn Header="Sender" DisplayMemberBinding="{Binding Sender}"/>
<GridViewColumn Header="Support-ID" DisplayMemberBinding="{Binding Support_ID}"/>
<GridViewColumn Header="Supporter" DisplayMemberBinding="{Binding Supporter}"/>
<GridViewColumn Header="Received" DisplayMemberBinding="{Binding ReceivedDate}"/>
</GridView>
</ListView.View>
</ListView>
</Grid>
Code behind:
private void createMailList()
{
_mails.Add(new Mail("LIC", "Lizenz geht nicht", "Xeun", "LIC.2013.01.10.002", "Xeun", "25.09.2013"));
_mails.Add(new Mail("CD", "Alles doof", "Xeun", "CD.2013.01.10.002", "Xeun", "25.09.2013"));
_mails.Add(new Mail("CD", "Re:Alles doof", "Xeun", "CD.2013.01.10.002", "Xeun", "25.09.2013"));
_mails.Add(new Mail("CD", "CD kaputt", "Xeun", "CD.2013.01.10.003", "Xeun", "25.09.2013"));
_mails.Add(new Mail("CD", "Geht nicht", "Xeun", "CD.2013.01.10.001", "Xeun", "25.09.2013"));
_mails.Add(new Mail("LIC", "Kaputt", "Xeun", "LIC.2013.01.10.001", "Xeun", "25.09.2013"));
}
public MainWindow()
{
InitializeComponent();
createMailList();
DataContext = _mails;
ICollectionView view = CollectionViewSource.GetDefaultView(_mails);
PropertyGroupDescription groupDescription = new PropertyGroupDescription("ID");
view.GroupDescriptions.Add(groupDescription);
view.GroupDescriptions.Add(new PropertyGroupDescription("Support_ID"));
}
}
public class GroupItemStyleSelector : StyleSelector
{
public override Style SelectStyle(object item, DependencyObject container)
{
Style s;
CollectionViewGroup group = item as CollectionViewGroup;
Window window = Application.Current.MainWindow;
if (!group.IsBottomLevel)
{
s = window.FindResource("FirstLevel") as Style;
}
else
{
s = window.FindResource("SecondLevel") as Style;
}
return s;
}
}
I hope I explained my problem well enough - I have attached a screenshot of the small app - the Groups marked as red only contain one item and should not be shown as group.
For both styles split the ControlTemplate in 2, one with an expander and one with out.
Create a converter which checks the if the group size (your group is of type CollectionViewGroup)
return yourGroup.Items.Count > 1
Place a DataTrigger as seen below in each style which checks the groups size via the converter
(your DataContext is your group so the binding is Binding="{Binding}"
xaml :
<ControlTemplate TargetType="{x:Type GroupItem}" x:Key="withExpander">
<Expander IsExpanded="True">
<Expander.Header>
.....
</Expander.Header>
<ItemsPresenter />
</Expander>
</ControlTemplate>
<ControlTemplate TargetType="{x:Type GroupItem}" x:Key="withOutExpander">
<ItemsPresenter />
</ControlTemplate>
<Style x:Key="FirstLevel" TargetType="{x:Type GroupItem}">
<Setter Property="Template" Value="{StaticResource withExpander}" />
<Style.Triggers>
<DataTrigger Binding="{Binding , Converter={StaticResource GroupSizeToExpanderConverter}" Value="False">
<Setter Property="Template" Value="{StaticResource withOutExpander}"/>
</DataTrigger>
</Style.Triggers>
</Style>
Edit :
*the converter value will be the Group itself (of type CollectionViewGroup)
The Converter :
public class GroupSizeToExpanderConverter: IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
CollectionViewGroup grp = (CollectionViewGroup)value;
return grp.Items.Count() > 1; // ALTERNATIVLY grp.ItemCount;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
here is my solution
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<Expander IsExpanded="True">
<Expander.Style>
<Style TargetType="Expander">
<Setter Property="Visibility" Value="Visible"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding ItemCount}" Value="1">
<Setter Property="Visibility" Value="Collapsed"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Expander.Style>
<Expander.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" FontWeight="Bold" Foreground="Gray" FontSize="22" VerticalAlignment="Bottom" />
<TextBlock Text="{Binding ItemCount}" FontSize="22" Foreground="Green" FontWeight="Bold" FontStyle="Italic" Margin="10,0,0,0" VerticalAlignment="Bottom" />
<TextBlock Text=" item(s)" FontSize="22" Foreground="Silver" FontStyle="Italic" VerticalAlignment="Bottom" />
</StackPanel>
</Expander.Header>
<Border BorderBrush="LightBlue" BorderThickness="2" Margin="0 2">
<ItemsPresenter />
</Border>
</Expander>
<ItemsPresenter>
<ItemsPresenter.Style>
<Style TargetType="ItemsPresenter">
<Setter Property="Visibility" Value="Collapsed"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding ItemCount}" Value="1">
<Setter Property="Visibility" Value="Visible"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ItemsPresenter.Style>
</ItemsPresenter>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>

Categories

Resources