wpf image not being shown in some ListBoxItems - c#

I Have a ListBox with an ItemTemplate defined as follows. My problem is the image is shown in only one item per type. i.e:
How do I make all the items show their relevant status?
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<ContentControl x:Name="status">
<ContentControl.Style>
<Style TargetType="ContentControl">
<Style.Triggers>
<DataTrigger Binding="{Binding Status}" Value="NotDownloaded">
<Setter Property="Content">
<Setter.Value>
<Image Source="/Images/help-file24.png"/>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Status}" Value="Downloaded">
<Setter Property="Content">
<Setter.Value>
<Image Source="/Images/file-complete24.png""/>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Status}" Value="Error">
<Setter Property="Content">
<Setter.Value>
<Image Source="/Images/file-warning24.png"/>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
<TextBlock Text="{Binding Url}" Margin="5,0" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>

i found this on stackoverflow
If you will use the image in multiple places, then it's worth loading
the image data only once into memory and then sharing it between all
Image elements.
To do this, create a BitmapSource as a resource somewhere:
<BitmapImage x:Key="MyImageSource" UriSource="../Media/Image.png" />
Then, in your code, use something like:
<Image Source="{StaticResource MyImageSource}" />
In my case, I found
that I had to set the Image.png file to have a build action of
Resource rather than just Content. This causes the image to be carried
within your compiled assembly.

Image is an UIElement, meaning it's part of the hierarchy of controls and can only have one parent at any given time.
What your template is doing is set the same Image control instance as the content of many ContentControl. So it only works for the very first ContentControl, and then fails as Image has already a parent.
You may try to replace your ContentControl with an Image and setting Image's source in your DataTriggers.

Related

WPF ToolTip Text Alignment

I have the following ListViewItem:
<GridViewColumn Width="{Binding ActualWidth,
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Grid}},
Converter={StaticResource MathConverter}, ConverterParameter=(x/10)*1}">
<GridViewColumn.Header>
<GridViewColumnHeader Content=" Total Fees "
HorizontalContentAlignment="Right" />
</GridViewColumn.Header>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding GarnishmentTotals.TotalFees, StringFormat={}{0:c}}"
TextAlignment="Right" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
The Style for this item is as follows:
<Style x:Key="MultipleGarnishmentsStyle" TargetType="ContentControl">
<Style.Triggers>
<DataTrigger Binding="{Binding Garnishments.Count, Converter={StaticResource GreaterThanEqualToBooleanConverter}, ConverterParameter=2}" Value="True"
h:TriggerTracing.TriggerName="MultipleGarnishmentsStyle_Trigger1"
h:TriggerTracing.TraceEnabled="True">
<!-- Leave the content alone and just change the format string -->
<Setter Property="TextBlock.FontWeight" Value="UltraBold" />
<Setter Property="ToolTip" Value="Employee has multiple garnishments. Double click to view details." />
</DataTrigger>
</Style.Triggers>
</Style>
I am having an issue with the alignment of the text within the ToolTip.
The text seems to be using the ListViewItems text alignment (Right). I have tried adding the following properties to teh style but nothing changes:
<Setter Property="TootlTip.HorizontalAlignment" Value="Left" />
<Setter Property="TootlTip.HorizontalContentAlignment" Value="Left" />
<Setter Property="TootlTip.Width" Value="300" />
Is there a way to either increase the ToolTip width so there is no wrapping of the text or make the ToolTip text left aligned.
I got the same problem and after some digging (RibbonToolTip is inheriting alignment from a textbox), I found a solution. It maybe late, but it would benefit others.
What you need to do is to setup you ToolTip style like this:
<Style TargetType="ToolTip">
<Setter Property="TextBlock.TextAlignment" Value="Left"/>
</Style>
Since Tooltip is a ContentControl you can customize its content as you want. Consider the following example:
<Grid>
<Button Content="Hi there!">
<Button.Style>
<Style TargetType="Button">
<Setter Property="ToolTip">
<Setter.Value>
<ToolTip MaxWidth="100" HorizontalContentAlignment="Center">
<TextBlock Text="fsdfasdfasdfasdfasdfasdfadsfasdf fadsfadsf adfa fdasfasdfasdfa adfasd" TextAlignment="Center" HorizontalAlignment="Center" TextWrapping="Wrap"/>
</ToolTip>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>
</Grid>
You can play around with the content's properties (in this case the TextBlock) in order to achieve the final look you want.

How to Change ContentControl `s Content on Toggle Button IsChecked Proprrty

Currently i am working on Changing the Content ( as image) of a container on toggle button IsChecked Proprty.
So i thought ContentControl would be a nice choice for a container. But i am not able to figure out how to achieve the result.
I created a resource of images in windows.resource
<Image Source="Resources/Desert.jpg" x:Key="image1"/>
<Image Source="Resources/Koala.jpg" x:Key="image2"/>
<Image Source="Resources/Lighthouse.jpg" x:Key="image3"/>
<Image Source="Resources/Chrysanthemum.jpg" x:Key="image4"/>
So i thought to Use the above resource to change the Content Property of a ContentControl by changing the ControlTemplate proprty by using Triggers where SourceName as (ToggleButton) and TargetName as (ContentControl) but its not working
SO how can I change the content of a ContentControl on toggleButton Ischeck property.
Edit
<ContentControl BorderBrush="Black" Name="cc">
<ControlTemplate>
<ControlTemplate.Triggers>
<Trigger SourceName="ToggleButton" Property="IsChecked" Value="True">
<Setter TargetName="cc" Property="Content" Value="{StaticResource image1}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</ContentControl>
I just tried as i have no idea how to do it.....
Any help are welcomed
You seem to have over complicated the situation unnecessarily. You can just use an Image control rather than a ContentControl. To alternate between two Images, you can simply do this with a DataTrigger:
<Image Source="Resources/Desert.jpg" x:Key="image1"/>
<StackPanel>
<ToggleButton Name="Button" Content="Change Image" Margin="10" />
<Image Margin="10,0,10,10">
<Image.Style>
<Style>
<Setter Property="Image.Source"
Value="/YourAppName;component/Resources/Desert.jpg" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=Button}"
Value="True">
<Setter Property="Image.Source"
Value="/YourAppName;component/Images/Resources/Koala.jpg" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</StackPanel>

Changing Conent Control template on Menu Item click?

Can you please tell me how to change content template when, in WPF, when it is clicked on different Menu Item headers. I've defined user control that I can put it as a template.
For example: Menu Items are: Home, Players, Team . when i click on Home I want that specific template in my Content Control to pop up, tehen when I click on Players I want another template (list of players) to pop in Content Control as template.
How to do that with triggers in XAML?
Thank you very much :)
You can use a ContentControl to host whatever your content will be, and set the ContentControl.ContentTemplate based on how you want to draw your content.
As a very basic example,
<ContentControl x:Name="MyContentControl">
<ContentControl.Style>
<Style TargetType="{x:Type ContentControl}">
<Style.Triggers>
<DataTrigger Binding="{Binding }" Value="Home">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<local:MyHomeUsercontrol />
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding }" Value="Players">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<local:MyPlayersUsercontrol />
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding }" Value="Team">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<local:MyTeamUsercontrol />
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style>
</ContentControl.Style>
</ContentControl>
And on MenuItem.Click
MyContentControl.Content = "Home"; // or "Players" or "Team"
In this example I'm using a string for the ContentControl.Content, however if you were to use a class object such as a HomeViewModel or PlayersViewModel, your XAML could be simplified to use implicit data templates, which are templates that automatically get used whenever WPF tries to draw a specific class
<Window.Resources>
<DataTemplate DataType="{x:Type HomeViewModel}">
<local:MyHomeUserControl />
</DataTemplate>
<DataTemplate DataType="{x:Type PlayersViewModel}">
<local:MyPlayersUserControl />
</DataTemplate>
<DataTemplate DataType="{x:Type TeamViewmModel}">
<local:MyTeamUserControl />
</DataTemplate>
</Window.Resources>
<ContentControl x:Name="MyContentControl" />
and
MyContentControl.Content = new HomeViewModel();
How about using a tab control with tab placement at the top? it would be much cleaner that way..
Edit; Example:
<TabControl>
<TabItem>
<TabItem.Header>
<TextBlock Text="Football header!"/>
</TabItem.Header>
<TabItem.Content>
<Button Content="Push for football!"/>
</TabItem.Content>
</TabItem>
</TabControl>
this might help also; http://www.switchonthecode.com/tutorials/the-wpf-tab-control-inside-and-out

WPF DataTemplate Binding depending on the type of a property

I have a collection of objects bound to a hierarchical data template, each of my objects have a property on them (lets call it Property "A") that is of a certain type. This type varies among each of the objects.
If the data template contains an image and some text, what would be the best way to change the image that is displayed in the template based on the type of property "A".
I know I could just stick this into a converter and do the binding translation manually in code, but with all the binding facilities available in WPF, I think theres probably a better way.
It's pretty simple to do this within your data template, if you create local data templates and use a ContentPresenter. This template presents objects of type MyObject, displaying an image whose source is determined by the type of the A property next to a TextBlock that displays the content of the Text property:
<DataTemplate DataType="{x:Type MyObject}">
<StackPanel Orientation="Horizontal">
<StackPanel.Resources>
<DataTemplate DataType="{x:Type Thing1}">
<Image Source="thing1.png"/>
</DataTemplate>
<DataTemplate DataType="{x:Type Thing2}">
<Image Source="thing2.png"/>
</DataTemplate>
</StackPanel.Resources>
<ContentPresenter Content="{Binding A}"/>
<TextBlock Text="{Binding Text}"/>
</StackPanel>
</DataTemplate>
If you want to use styles to do this instead, you're going to run into a problem, because data triggers want to look at property values, and the type of the A property is not, itself, exposed as a property.
Unless, of course, you implement one:
public Type AType { get { return A.GetType(); } }
(You'll also need to raise PropertyChanged for AType when the value of A changes.) Once you've done this, you should be able to implement a data trigger in a style, e.g.:
<Style TargetType="Image">
<Setter Property="Source" Value="default.png"/>
<Style.Triggers>
<DataTrigger Binding="{Binding AType}" Value="{x:Type Thing1}">
<Setter Property="Source" Value="thing1.png"/>
</DataTrigger>
<DataTrigger Binding="{Binding AType}" Value="{x:Type Thing2}">
<Setter Property="Source" Value="thing2.png"/>
</DataTrigger>
</Style.Triggers>
</Style>
I think You can do that with triggers.
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="Path">
<Style.Triggers>
<DataTrigger Binding="{Binding TheProperty}" Value="TheValue">
<Setter Property="Source" Value="NewPath"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
DataTemplateSelector doesn't seem to be a good choice here since you have the same template for all values of A.
Use DataTriggers:
<DataTemplate>
<StackPanel>
<Image x:Name="image" />
<TextBlock>Your text</TextBlock>
</StackPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=A}" Value="ValueToCheck1">
<DataTrigger.Setters>
<Setter Property="Source" Value="Image1.png" TargetName="image" />
</DataTrigger.Setters>
</DataTrigger>
<DataTrigger Binding="{Binding Path=A}" Value="ValueToCheck2">
<DataTrigger.Setters>
<Setter Property="Source" Value="Image2.png" TargetName="image" />
</DataTrigger.Setters>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
Haven't tested it, but the idea is like that.

WPF DataGrid Binding DataGridCell Content

This is hopefully going to be a really simple answer, I'm just not seeing the proverbial wood for the trees I think.
I've got a DataGridCell style in which I want to bind the content of the cell to the source property of an image, here's the XAML I'm using at the moment:
<Style x:Key="DataGridImageCellStyle" TargetType="{x:Type toolkit:DataGridCell}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type toolkit:DataGridCell}">
<Border Background="Transparent"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="0"
SnapsToDevicePixels="True">
<Image Source="{Binding RelativeSource={RelativeSource AncestorType=toolkit:DataGridCell}, Path=Content}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Note that at the moment i'm binding the Image Source to Content.. which doesnt work, i've also tried Value, which didn't work!
So my question is, nice and simply.. what is the correct binding to use to get the cell's content into the source property of this image?
Thanks in advance!
Pete
If the column is a DataGridTextColumn then you might be able to bind to the Text property of the TextBlock that is its content:
<Image Source="{Binding RelativeSource=
{RelativeSource AncestorType=DataGridCell}, Path=Content.Text}" />
That's really a hack, though. If you want to display an image in a column, you should probably use a DataGridTemplateColumn:
<DataGridTemplateColumn Header="...">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Image Source="{Binding SomeProperty}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
Where SomeProperty is the property of your row object that has the image path.

Categories

Resources