Okay so my problem is that I generate some elements on the fly, as linked to an array (for each element on the array there is another item in the XAML). I'm doing this with a TreeView control, albiet following an online example (which has been working well so far).
In this example, the groups are families and within each ... well, it's easier to show in an image here. Family is a class which contains an ObservableCollection of FamilyMembers, both of which are used to populate the TreeView.
Here's the main business:
<TreeView Name="trvFamilies">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type self:Family}" ItemsSource="{Binding Members}">
<StackPanel Orientation="Horizontal">
<Image Source="{StaticResource ImageGroup}" Margin="0,0,5,0" />
<TextBlock Text="{Binding Name}" />
<TextBlock Text=" [" Foreground="Blue" />
<TextBlock Text="{Binding Members.Count}" Foreground="Blue" />
<TextBlock Text="]" Foreground="Blue" />
</StackPanel>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type self:FamilyMember}">
<StackPanel Orientation="Horizontal">
<Image Source="{StaticResource ImageUserMale}" Margin="0,0,5,0" />
<TextBlock Text="{Binding Name}" />
<TextBlock Text=" (" Foreground="Green" />
<TextBlock Text="{Binding Age}" Foreground="Green" />
<TextBlock Text=" years)" Foreground="Green" />
</StackPanel>
</DataTemplate>
</TreeView.Resources>
</TreeView>
This all works fine, but here's my problem: I have a male image for if a family member is male and a female one for if the family member is female. I don't know how to get at the elements to set the image based on this criterion. As you can see, at the moment the images are static.
Thanks!
You may use a DataTrigger, e.g. on a potential enum Gender property of your FamilyMember:
<Image>
<Image.Style>
<Style TargetType="Image">
<Setter Property="Source" Value="{StaticResource ImageUserUnknownGender}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Gender}" Value="Male">
<Setter Property="Source" Value="{StaticResource ImageUserMale}"/>
</DataTrigger>
<DataTrigger Binding="{Binding Gender}" Value="Female">
<Setter Property="Source" Value="{StaticResource ImageUserFemale}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
Related
I have a DataGrid that consists of some columns. In one DataGridTemplateColumn, I want to use a condition. If the condition is False, it should display a single bound property. If the condition is True, it should display multiple bound properties (that's what I can't accomplish). How can I use WrapPanel under DataTrigger Setter?
My XAML code:
<DataGrid x:Name="DG_SipList" ItemsSource="{Binding Items3}" Margin="0 8 0 0" CanUserSortColumns="False" CanUserAddRows="False" AutoGenerateColumns="False" VerticalAlignment="Top" HorizontalAlignment="Left" materialDesign:DataGridAssist.CellPadding="13 8 8 8" materialDesign:DataGridAssist.ColumnHeaderPadding="8" IsReadOnly="True" HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible" >
<DataGrid.Resources>
<Style TargetType="TextBlock" x:Key="cfgText">
<Style.Triggers>
<DataTrigger Binding="{Binding Tag, RelativeSource={RelativeSource Self}}" Value="False">
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="FontStyle" Value="Italic"/>
<Setter Property="TextDecorations" Value="Underline"/>
<Setter Property="Foreground" Value="Red"/>
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="TextWrapping" Value="WrapWithOverflow" />
</DataTrigger>
</Style.Triggers>
</Style>
<Style TargetType="TextBlock" x:Key="cfgText2">
<Style.Triggers>
<DataTrigger Binding="{Binding Tag, RelativeSource={RelativeSource Self}}" Value="True">
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="FontStyle" Value="Italic"/>
<Setter Property="Foreground" Value="Red"/>
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="TextWrapping" Value="WrapWithOverflow" />
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTemplateColumn Header="START" IsReadOnly="False">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox x:Name="cb_MontajStart" Checked="cb_MontajStart_Checked" Unchecked="cb_MontajStart_Unchecked" IsChecked="{Binding LISTE_MONTAJ_START}" HorizontalAlignment="Center"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="ID">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=LISTE_KIMLIK}" Tag="{Binding Path=LISTE_MONTAJ_START}" Style="{StaticResource cfgText2}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="PRODUCT" MaxWidth="450">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock>
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding konfTanim}" Value="False">
<Setter Property="Text" Value="{Binding LISTE_URUN}"/>
</DataTrigger>
<DataTrigger Binding="{Binding konfTanim}" Value="True">
<Setter>
<!--This is what I can not combine more than one textblock under Datatrigger Setter-->
<WrapPanel Orientation="Horizontal" MaxWidth="450">
<TextBlock Text="{Binding Path=yeni_ModelTanim}"/>
<TextBlock Text="{Binding Path=MT4}" Tag="{Binding Path=monStd4}" Style="{StaticResource cfgText}"/>
<TextBlock Text="{Binding Path=MT5}" Tag="{Binding Path=monStd5}" Style="{StaticResource cfgText}"/>
<TextBlock Text="{Binding Path=MT6}" Tag="{Binding Path=monStd6}" Style="{StaticResource cfgText}"/>
</WrapPanel>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<!-- ........................................................... -->
<DataGridTemplateColumn x:Name="txt_Configuration" Header="configuration" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<WrapPanel Orientation="Horizontal" MaxWidth="450">
<TextBlock Text="{Binding Path=yeni_ModelTanim}"/>
<TextBlock Text="{Binding Path=MT4}" Tag="{Binding Path=monStd4}" Style="{StaticResource cfgText}"/>
<TextBlock Text="{Binding Path=MT5}" Tag="{Binding Path=monStd5}" Style="{StaticResource cfgText}"/>
<TextBlock Text="{Binding Path=MT6}" Tag="{Binding Path=monStd6}" Style="{StaticResource cfgText}"/>
</WrapPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
In case of multiple different representations of the same type, depending on a flag or other properties, you have to implement a custom DataTemplateSelector and a data template for each representation, e.g.:
<DataTemplate x:Key="KonfTanimFalseTemplate">
<TextBlock Text="{Binding LISTE_URUN}"/>
</DataTemplate>
<DataTemplate x:Key="KonfTanimTrueTemplate">
<WrapPanel Orientation="Horizontal" MaxWidth="450">
<TextBlock Text="{Binding Path=yeni_ModelTanim}"/>
<TextBlock Text="{Binding Path=MT4}" Tag="{Binding Path=monStd4}" Style="{StaticResource cfgText}"/>
<TextBlock Text="{Binding Path=MT5}" Tag="{Binding Path=monStd5}" Style="{StaticResource cfgText}"/>
<TextBlock Text="{Binding Path=MT6}" Tag="{Binding Path=monStd6}" Style="{StaticResource cfgText}"/>
</WrapPanel>
</DataTemplate>
The data template selector checks the konfTanim property and returns the appropriate data template.
public class KonfTanimDataTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (!(container is FrameworkElement frameworkElement) || !(item is YourItemType yourItem))
return null;
var dataTemplateName = yourItem.konfTanim ? "KonfTanimTrueTemplate" : "KonfTanimFalseTemplate";
return (DataTemplate) frameworkElement.FindResource(dataTemplateName);
}
}
You could also pass in the template names via properties to avoid hard-coding them here. This can help to reuse the selector in your application. In your DataGrid, you could add the data templates to the Resources with an instance of the selector and use it in the template column like this:
<DataGrid ItemsSource="{Binding YourItemTypeList}" AutoGenerateColumns="False">
<DataGrid.Resources>
<DataTemplate x:Key="KonfTanimFalseTemplate">
<TextBlock Text="{Binding LISTE_URUN}"/>
</DataTemplate>
<DataTemplate x:Key="KonfTanimTrueTemplate">
<WrapPanel Orientation="Horizontal" MaxWidth="450">
<TextBlock Text="{Binding Path=yeni_ModelTanim}"/>
<TextBlock Text="{Binding Path=MT4}" Tag="{Binding Path=monStd4}" Style="{StaticResource cfgText}"/>
<TextBlock Text="{Binding Path=MT5}" Tag="{Binding Path=monStd5}" Style="{StaticResource cfgText}"/>
<TextBlock Text="{Binding Path=MT6}" Tag="{Binding Path=monStd6}" Style="{StaticResource cfgText}"/>
</WrapPanel>
</DataTemplate>
<local:KonfTanimDataTemplateSelector x:Key="KonfTanimDataTemplateSelector"/>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTemplateColumn CellTemplateSelector="{StaticResource KonfTanimDataTemplateSelector}"/>
</DataGrid.Columns>
</DataGrid>
Isn't there any other way I can do this just using XAML (without C#)?
There is not really anything bad about having a data template selector for complex conditions.
Choosing a DataTemplate Based on Properties of the Data Object
However, often having a flag to determine the type of an object is a sign that the corresponding class should be split into two different types. In this case, you could create a data template with a specific DataType for both types. Unfortunately, automatic data template selection by type works in other items controls, but in DataGrid or more specifically a template column, you would have to use workarounds, which might be more cumbersome than to just create a selector that might as well be reusable in other columns.
I have a ListBox. This ListBox has custom controls. For example, image, textblocks, etc. Initially textblocks are collapsed, image is visible. I want to make the textblocks visible when user enter with mouse and change opacity of image in that item. But I can't access listboxitems controls. I named them but they don't show up.How can I achieve that ? My ListBox XAML codes:
<ListBox SelectionChanged="MoviesDisplay_OnSelectionChanged" ScrollViewer.HorizontalScrollBarVisibility="Disabled" Background="Black" x:Name="MoviesDisplay">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid x:Name="MoviesGrid" Height="355" Width="240" Margin="10,20,20,3" HorizontalAlignment="Left">
<Image x:Name="MoviePoster" Opacity="1" Source="{Binding Poster}"></Image>
<TextBlock Visibility="Collapsed" x:Name="MovieName" FontSize="18" Text="{Binding Name}" Foreground="White" Margin="0,15,0,321"></TextBlock>
<TextBlock Visibility="Collapsed" x:Name="MovieGenre" FontSize="16" Text="" Foreground="White" Margin="0,34,0,302"></TextBlock>
<TextBlock Visibility="Collapsed" x:Name="MovieReleaseDate" FontSize="16" Text="{Binding ReleaseDate}" Foreground="White" Margin="0,53,164,284"></TextBlock>
<materialDesign:RatingBar Visibility="Collapsed" Foreground="White"
Value="{Binding Rating}"
x:Name="MovieRatingBar" Margin="59,314,60,17"
/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
private async void Window_Loaded(object sender, RoutedEventArgs e)
{
client.GetConfig();
var popularMovies = await client.GetMoviePopularListAsync("en", 1);
PopularMovies.Clear();
foreach (var movie in popularMovies.Results)
{
// ImgListUrls.Add(client.GetImageUrl("w500",movie.PosterPath).AbsoluteUri);
Movie mov = new Movie()
{
Id = movie.Id,
Name = movie.OriginalTitle,
ReleaseDate = movie.ReleaseDate.Value.ToShortDateString(),
Poster = client.GetImageUrl("w500", movie.PosterPath).AbsoluteUri,
Rating = movie.VoteAverage
};
PopularMovies.Add(mov);
}
MoviesDisplay.ItemsSource = PopularMovies;
// DownloadImages(ImgListUrls);
}
You don't need to access these elements in code behind. Add Styles with DataTriggers instead, e.g.:
<Image Source="{Binding Poster}">
<Image.Style>
<Style TargetType="Image">
<Setter Property="Opacity" Value="1"/>
<Style.Triggers>
<DataTrigger
Binding="{Binding IsMouseOver,
RelativeSource={RelativeSource AncestorType=ListBoxItem}}"
Value="True">
<Setter Property="Opacity" Value="0.5"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
Put the TextBlocks in a StackPanel and add a similar Style:
<StackPanel>
<StackPanel.Style>
<Style TargetType="StackPanel">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger
Binding="{Binding IsMouseOver,
RelativeSource={RelativeSource AncestorType=ListBoxItem}}"
Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<TextBlock FontSize="18" Text="{Binding Name}" Foreground="White"/>
<TextBlock FontSize="16" Text="{Binding ReleaseDate}" Foreground="White"/>
</StackPanel>
I need to show only the Icon in the combo box if the combo box is clicked the icon and the text needs to be shown. As I am not familiar with how to achieve this.
Please help me in achieving this.
<ComboBox Name="cmbColors">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Rectangle Fill="{Binding Name}" Width="16" Height="16" Margin="0,2,5,2" />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
This will show the rectangle and text in the combo box and the drop down of the combo box. But my requirement is only to show the color filled rectangle in the combo box.
I am not sure whether I understand what you are trying to do, but my best guess is that you want to hide the text block if some other control has focus. If so, you can do something like this:
<ComboBox>
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Rectangle Fill="{Binding Name}" Width="16" Height="16" Margin="0,2,5,2" />
<TextBlock x:Name="text" Text="{Binding Name}" />
</StackPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsKeyboardFocusWithin, RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}" Value="False">
<Setter TargetName="text" Property="Visibility" Value="Collapsed" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
If you are instead trying to say that you want a different template for the header than for the dropdown, then you could do something like described in one of the answers to this question.
<ComboBox>
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Rectangle Fill="{Binding Name}" Width="16" Height="16" Margin="0,2,5,2" />
<TextBlock x:Name="text" Text="{Binding Name}" />
</StackPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type ComboBoxItem}}}" Value="{x:Null}">
<Setter TargetName="text" Property="Visibility" Value="Collapsed" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
First of all, I will try to describe the context of what I need.
I have an application, which display a dashboard like this :
Dashboard-with-KPI
On each line of those KPIs, when there is a valueProcessed I want to see :
aTitle : valueToProcess/valueProcessed [%]
But when there isn't any valueProcessed I need this :
aTitle : 0 [n/a]
In order to achieve it, I used a DataTrigger like this :
<StackPanel Grid.Column="1" Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right">
<StackPanel>
<StackPanel.Style>
<Style TargetType="StackPanel">
<Setter Property="Visibility" Value="Visible" />
<Style.Triggers>
<DataTrigger Binding="{Binding NbLocationToInstall}" Value="0">
<Setter Property="Visibility" Value="Hidden" />
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<TextBlock Style="{StaticResource TextBlock_Default_Dashboard}" Text="{Binding NbLocationInstalled}"/>
<TextBlock Style="{StaticResource TextBlock_Default_Dashboard_NoSpace}" Text="/" />
<TextBlock Style="{StaticResource TextBlock_Default_Dashboard}" Text="{Binding NbLocationToInstall}"/>
<TextBlock Style="{StaticResource TextBlock_Default_Dashboard}" Text="{Binding PrLocationInstalled, StringFormat={}[{0:0.##} %]}" />
</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<StackPanel.Style>
<Style TargetType="StackPanel">
<Setter Property="Visibility" Value="Hidden" />
<Style.Triggers>
<DataTrigger Binding="{Binding NbLocationToInstall}" Value="1">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<TextBlock Style="{StaticResource TextBlock_Default_Dashboard}" Text="{Binding NbLocationToInstall}"/>
<TextBlock Style="{StaticResource TextBlock_Default_Dashboard}" Text="[n/a]" />
</StackPanel>
</StackPanel>
Displaying a StackPanel depends on a binding value called NbLocationToInstall.
This solution works but, I have a lot of rows of KPI to display, and I don't want to repeat this block (=> n rows mean n block like this, just binding values will change).
So I have decided to create a dictionary, there I set my style :
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Dictionary.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style x:Key="ValidTrigger" TargetType="StackPanel">
<Setter Property="Visibility" Value="Visible" />
<Style.Triggers>
<DataTrigger Binding="{Binding NbLocationToInstall}" Value="0">
<Setter Property="Visibility" Value="Hidden" />
</DataTrigger>
</Style.Triggers>
</Style>
<Style x:Key="InvalidTrigger" TargetType="StackPanel">
<Setter Property="Visibility" Value="Hidden" />
<Style.Triggers>
<DataTrigger Binding="{Binding NbLocationToInstall}" Value="1">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
</UserControl.Resources>
And now, I can use it like this :
<StackPanel Grid.Column="1" Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Style="{StaticResource ValidTrigger}">
<TextBlock Style="{StaticResource TextBlock_Default_Dashboard}" Text="{Binding NbLocationInstalled}"/>
<TextBlock Style="{StaticResource TextBlock_Default_Dashboard_NoSpace}" Text="/" />
<TextBlock Style="{StaticResource TextBlock_Default_Dashboard}" Text="{Binding NbLocationToInstall}"/>
<TextBlock Style="{StaticResource TextBlock_Default_Dashboard}" Text="{Binding PrLocationInstalled, StringFormat={}[{0:0.##} %]}" />
</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Style="{StaticResource InvalidTrigger}">
<TextBlock Style="{StaticResource TextBlock_Default_Dashboard}" Text="{Binding NbLocationToInstall}"/>
<TextBlock Style="{StaticResource TextBlock_Default_Dashboard}" Text="[n/a]" />
</StackPanel>
</StackPanel>
But how can I change the binding value of DataTrigger style ValidTrigger ?
This is valid here for this example, given in the context, but for other rows, I want to pass another binding variable. And there, it is NbLocationToInstall, defined in ResourceDictionary.
Many thanks for any help.
According to the suggestion, I made a review of my code.
First of all, this is the XAML code definition :
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Dictionary.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style x:Key="ValidTrigger" TargetType="StackPanel">
<Setter Property="Visibility" Value="Visible" />
<Style.Triggers>
<DataTrigger Binding="{Binding ValueToProcess}" Value="0">
<Setter Property="Visibility" Value="Hidden" />
</DataTrigger>
</Style.Triggers>
</Style>
<Style x:Key="InvalidTrigger" TargetType="StackPanel">
<Setter Property="Visibility" Value="Hidden" />
<Style.Triggers>
<DataTrigger Binding="{Binding ValueToProcess}" Value="0">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
</UserControl.Resources>
<!-- Detailed Information -->
<GroupBox Header="{x:Static lang:Resource.DetailedInformation}" Grid.Column="0" Grid.Row="0" Margin="5" Style="{StaticResource GroupBox_Default_Dashboard}">
<StackPanel>
<UniformGrid HorizontalAlignment="Stretch" Columns="2">
<TextBlock Style="{StaticResource TextBlock_Default}" HorizontalAlignment="left" Text="{x:Static lang:Resource.DeploymentTime}" />
<TextBlock Style="{StaticResource TextBlock_Default}" HorizontalAlignment="Right">
<TextBlock.Text>
<MultiBinding StringFormat="{}{0:00} h {1:00;00} min">
<Binding Path="Time.Hours" />
<Binding Path="Time.Minutes" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</UniformGrid>
<ListBox ItemsSource="{Binding KPIs}" BorderBrush="Transparent" Background="Transparent" HorizontalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="0.45" />
</Grid.ColumnDefinitions>
<TextBlock Style="{StaticResource TextBlock_Default}" HorizontalAlignment="Left" Text="{Binding Label}"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Style="{StaticResource ValidTrigger}">
<TextBlock Style="{StaticResource TextBlock_Default_Dashboard}" Text="{Binding ValueProcessed}"/>
<TextBlock Style="{StaticResource TextBlock_Default_Dashboard_NoSpace}" Text="/" />
<TextBlock Style="{StaticResource TextBlock_Default_Dashboard}" Text="{Binding ValueToProcess}"/>
<TextBlock Style="{StaticResource TextBlock_Default_Dashboard}" Text="{Binding ValueProcessed, StringFormat={}[{0:0.##} %]}" />
</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Style="{StaticResource InvalidTrigger}">
<TextBlock Style="{StaticResource TextBlock_Default_Dashboard}" Text="{Binding ValueToProcess}"/>
<TextBlock Style="{StaticResource TextBlock_Default_Dashboard}" Text="[n/a]" />
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</GroupBox>
This is the KPI model :
/// <summary>
/// provide a container to display a simple KPI
/// </summary>
public class KPI
{
// props
public string Label { get; private set; }
public double ValueToProcess { get; private set; }
public double ValueProcessed { get; private set; }
public double Percentage { get; private set; }
// default ctor
public KPI(string label, double valueToProcess, double valueProcessed)
{
this.Label = label;
this.ValueToProcess = valueToProcess;
this.ValueProcessed = valueProcessed;
this.Percentage = (valueToProcess == 0) ? Double.NaN
: ValueProcessed / ValueToProcess * 100;
}
}
This is the declaration :
ObservableCollection<KPI> _KPIs;
public ObservableCollection<KPI> KPIs
{
get { return _KPIs; }
set
{
_KPIs = value;
RaisePropertyChanged("KPIs");
}
}
This is the definition :
KPIs = new ObservableCollection<KPI>()
{
{ new KPI(Lang.Resource.Label1, 5, 0) },
{ new KPI(Lang.Resource.Label2, 0, 0) },
{ new KPI(Lang.Resource.Label3, 0, 0) }
};
And It works perfectly.
I hope it could help anyone else.
I've created a status bar:
<StatusBar>
<StatusBarItem >
<WrapPanel>
<Image Source="/MyApp;component/Images/icon.png" />
<TextBlock Name="_StatusbarUser" Text="Username" />
</WrapPanel>
</StatusBarItem>
</StatusBar>
How to create a trigger, when i set the textblock visibility to collapse,
it will also triger parent status bar visibility.
I've try using style bellow, but didn't work
<StatusBar Grid.Row="2" Name="_Statusbar">
<StatusBar.Resources>
<Style TargetType="{x:Type StatusBarItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type TextBlock}}, Path=Visibility}" Value="Collapsed">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</StatusBar.Resources>
<StatusBarItem>
<WrapPanel>
<Image Source="/MyApp;component/Images/icon.png" />
<TextBlock Name="_StatusbarUser" Text="Username" />
</WrapPanel>
</StatusBarItem>
</StatusBar>
Help please, thx
Better bind parent property to child property:
<StatusBar>
<StatusBarItem Visibility="{Binding ElementName=_StatusbarUser, Path=Visibility}">
<WrapPanel>
<Image Source="/MyApp;component/Images/icon.png" />
<TextBlock Name="_StatusbarUser" Text="Username" />
</WrapPanel>
</StatusBarItem>
</StatusBar>