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>
Related
in my WPF application I have a listview that only appears if a bound item has an values, this works like so
<ListView Grid.Row="1" Grid.Column="1" Margin="0,5,0,20" BorderThickness="0"
ItemContainerStyle="{StaticResource SelectionlessListViewItemStyle}"
ItemsSource="{Binding MissingAssets}">
<ListView.Style>
<Style TargetType="ListView">
<Style.Triggers>
<Trigger Property="HasItems" Value="False">
<Setter Property="Visibility" Value="Collapsed"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</ListView.Style>
So this will only display the listview if MissingAssets has any values and works fine, above that I wanted a textblock as a header to just say "The following assets could not be found", and I want to hide this text of course if this listview is hidden too, I tried implementing it like this
<TextBlock Grid.Row="0" Grid.Column="1" VerticalAlignment="Center" FontWeight="Bold" Text="The following assets could not be found">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding MissingAssets}" Value="">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
But for some reason it won't hide even if MissingAssets is empty, I've tried using several different things in Value="" but nothing gets it to work. Is there a property or something I'm forgetting to set?
Thanks
You have many options here. The simplest should be to bind the TextBlock.Visibility to the ListView.Visibilty:
<StackPanel>
<TextBlock Visibility="{Binding Elementname="MissingAssetsListView", Path="Visbibility" />
<ListView x:Name="MissingAssetsListView" />
</StackPanel>
Found a workaround, I created a new string property in my C# code that remains blank unless missing assents are found, if they are found I populate the string and bind that string to a label in my XAML, so if the string is empty then there will be no visible label on the UI
I have this text box:
<TextBox/>
I want to add a watermark to it to say, Enter your message here...
Since its not supported out of the box, this successfully does the trick:
<Style TargetType="TextBox" xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Style.Resources>
<VisualBrush x:Key="CueBannerBrush" AlignmentX="Left" AlignmentY="Center" Stretch="None">
<VisualBrush.Visual>
<Label Content="Enter your message here..." Foreground="LightGray" Padding="10 0 0 0" />
</VisualBrush.Visual>
</VisualBrush>
</Style.Resources>
<Style.Triggers>
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="Background" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
But is there a way to extend TextBox with a XAML property for WatermarkText, as follows and have my style pick it up and use it, or is there some other way to do it (C#, etc.)?
<TextBox WatermarkText="Enter your message here..."/>
The best way to do this is using Attached Dependency Properties that you can bind in the style. Just keep in mind that binding an attached dependency property is
Text={Binding (AttachedPropertyName)}
The () make the trick.
Have a look at Mahapps. It's a nice design framework and providing a TextBoxHelper class doing all this. It's open source so you can see how it is implemented using attached properties.
The easiest way to do what I need is to just put a label in the same position as the text box without hit test visibility in the .xaml:
<TextBox Name="Username" Grid.Row="2" Height="40" FontFamily="Segoe UI" FontSize="20" VerticalContentAlignment="Center" TextChanged="Username_TextChanged"/>
<Label Name="UsernameLabel" Content="Username" Grid.Row="2" FontFamily="Segoe UI" FontSize="20" Foreground="LightGray" Padding="5" IsHitTestVisible="False" />
In the .cs:
private void Hostname_TextChanged(object sender, TextChangedEventArgs e)
{
UpdateLabel(Hostname, HostnameLabel);
}
private void UpdateLabel(TextBox textBox, Label label)
{
label.Visibility = String.IsNullOrWhiteSpace(textBox.Text) ? Visibility.Visible : Visibility.Hidden;
}
This works for password boxes too, which are sealed, so you cannot inherit them anyways if you tried to extend sealed controls.
I am trying to create a custom ListBox control in WPF for a chat Messenger. I am using an ellipse to show the online/offline user. The ellipse is to be displayed on left and some text in center of the ListBoxItem.
I want to set the ellipse fill propert to red/green based on some variable.
This is what I have done :
<ListBox Name="myList" HorizontalAlignment="Left" Height="232" Margin="117,74,0,0" VerticalAlignment="Top" Width="207">
<ListBox.ItemTemplate>
<DataTemplate>
<DockPanel>
<Ellipse Name="ellipse" Fill="Red" DockPanel.Dock="Left">
<Ellipse.Triggers>
<Trigger Property="{Binding Online}" Value="True">
<Setter TargetName="ellipse" Property="Ellipse.Fill" Value="Green"/>
</Trigger>
</Ellipse.Triggers>
</Ellipse>
<TextBlock Text="{Binding text}"></TextBlock>
</DockPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
and in the code :
myList.Items.Add(new { text="Hello",Online="True" });
I am getting an error as
Cannot find the static member 'FillProperty' on the type 'ContentPresenter'.
What am I doing wrong here?
Obviously this is wrong: Property="{Binding Online}"
Also you should use a Style for triggers, no need to set TargetName, and you need to take precedence into consideration, and use a Setter for the default value.
you are actually misleading WPF with some of these concerns.
Binding A property on trigger will not work. you have to use DataTrigger insteed of Triggers.
Implementing Trigger on the Fly for any control. most of the times not work. So go with Styles.
While you are creating Ellipse in template make sure you have created enough size for it. So that can be visible to users.
try this.
<Window.Resources>
<Style x:Key="elstyle" TargetType="Ellipse">
<Setter Property="Height" Value="5"/>
<Setter Property="Width" Value="5"/>
<Setter Property="Fill" Value="Red"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Online}" Value="true">
<Setter Property="Fill" Value="Green"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<ListBox x:Name="myList" HorizontalAlignment="Left" Height="232" Margin="117,74,0,0" VerticalAlignment="Top" Width="207">
<ListBox.ItemTemplate>
<DataTemplate>
<DockPanel>
<Ellipse Name="ellipse" Margin="5" DockPanel.Dock="Left" Style="{DynamicResource elstyle}">
</Ellipse>
<TextBlock Text="{Binding Name}"></TextBlock>
</DockPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
code behind .
public MainWindow()
{
Random r = new Random();
InitializeComponent();
for (int i = 0; i < 10; i++)
{
myList.Items.Add(new { Name = "Name" + i.ToString(), Online = Convert.ToBoolean(r.Next(-1, 1)) });
}
}
You need to set the initial colour via a Setter and not in XAML. For more information and see this question: Change the color of ellipse when mouse over
there are a few issues in your XAML
set the size of your Ellipse
you need to use Style instead of Ellipse.Triggers
set your Fill color in your Style if you wane be able to change it in XAML by some condition
here an working example for your problem
<DataTemplate>
<!--<DockPanel> juste because i like StackPanel-->
<StackPanel Orientation="Horizontal">
<!--<Ellipse Name="ellipse" Fill="Red" DockPanel.Dock="Left">-->
<Ellipse Name="ellipse" Width="15" Height="15">
<!--<Ellipse.Triggers>-->
<Ellipse.Style>
<Style TargetType="Ellipse">
<Setter Property="Fill" Value="Red"/>
<Style.Triggers>
<!--<Trigger Property="{Binding Online}" Value="True">-->
<DataTrigger Binding="{Binding Online}" Value="True">
<Setter Property="Fill" Value="LimeGreen"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
<TextBlock Text="{Binding text}"/>
</StackPanel>
</DataTemplate>
I'm new to the styling part of WPF. What I want to do is to get the value of an attached property in a setter, e.g.:
<Trigger Property="SomeProperty" Value="SomeValue">
<Setter Property="SomeProperty"
Value="(My attached property, let's say lcl:MyClass.MyString)"/>
</Trigger>
I know that you can get something to this effect using a {TemplateBinding lcl:MyClass.MyString} in a ControlTemplate. My question is: can you do this in a style, without using a ControlTemplate?
You can try to use:
<Setter Property="SomeProperty" Value="{Binding Path=(lcl:MyClass.MyString), RelativeSource={RelativeSource self}}"/>
if your attached property applies to the element as your style. If not, you can use RelativeSource or ElementName to find the appropriate element.
I am not sure how you have done that since your code lacks of details. Below code works:
<UserControl.Resources>
<Style x:Key="LabelStyle" TargetType="{x:Type Label}">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Content"
Value="{Binding Path=(TestWebBrowser:AttachP.ValueEditorState), RelativeSource={RelativeSource self}}"/>
</Trigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
<StackPanel>
<Label x:Name="label" TestWebBrowser:AttachP.ValueEditorState="HelloWorld" Style="{StaticResource LabelStyle}"/>
<Button Content="Disable Label" Click="Button_Click"/>
</StackPanel>
Button's click event handler will set Label's IsEnabled to false to trigger the trigger. And note that you have to use Path= with parenthesis in the binding.
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.