I would like to add the Live Tile effect to the tiles on my wpf app layout. I'm using the MahApps.Metro library for the visuals. Here is an example of one of the tiles that I have on the layout -
<Controls:Tile Height="110" Background="#9c6b50" Width="180" VerticalAlignment="Top" HorizontalAlignment="Right" Margin="0,105,33,0">
<Controls:Tile.Content>
<TextBlock Text="Setup Your Savings Account" TextWrapping="Wrap" Width="121" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Controls:Tile.Content>
</Controls:Tile>
I'd like the end product of the tile to switch between these two texts:
Setup your Savings account
Click here to Setup your savings account
The generally accepted way to do this is by binding the Text property. A binding would look like this:
<TextBlock Text="{Binding Path=TileText}" TextWrapping="Wrap" Width="121" HorizontalAlignment="Center" VerticalAlignment="Center"/>
What this does is bind the value of the TextBlock to a property called TileText on the DataContext of the control. You will need to look into DataContext and binding in WPF to understand this.
Once you have a class with the property:
public string TileText
{
get {...}
set {...}
}
And the class is set as the DataContext of the Tile control you can change the value of the TileText property and it will change the text of the TextBlock. This is a simple example of MVVM design and can be a good first step in understanding smart WPF design practices.
Cheers,
Eric
Try this!
<controls:Tile Height="110" Background="#9c6b50" Width="180" VerticalAlignment="Top" HorizontalAlignment="Right" Margin="0,105,33,0">
<controls:Tile.Style>
<Style TargetType="controls:Tile">
<Setter Property="Content">
<Setter.Value>
<TextBlock Text="Setup Your Savings Account" TextWrapping="Wrap" Width="121" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Content">
<Setter.Value>
<TextBlock Text="Click here to Setup Your Savings Account" TextWrapping="Wrap" Width="121" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</controls:Tile.Style>
</controls:Tile>
Related
I have a Button style and this style contains an icon and a text. I would like to bind the text.
How can I achieve that?
<Style TargetType="{x:Type Button}" x:Key="ConnectedButton">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="FlowDirection" Value="LeftToRight"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Padding="5 0"
Width="80"
Height="30"
Margin="5">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Text="{Binding Connect}"
Margin="3 0" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Text="{StaticResource ConnectIcon}"
Style="{StaticResource Icon_Text}" Margin="3 0"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Use the style in MainWindow.xaml:
<Button Style="{StaticResource ConnectedButton}" Margin="10,15,0,10" x:Name="cnct_btn" Content="{StaticResource Connect}" Height="40" Width="80 " HorizontalAlignment="Left" VerticalAlignment="Center" Click="Cnct_Click"/>
MainWindow.xaml.cs
bool test = false;
//...
if (test)
{
cnct_btn.Content = "Connect";
}
else
{
cnct_btn.Content = "Not Connected";
}
I have tried Text={Binding Connect} but it doesn't work.
In a control template, you have to use a TemplateBinding to access a property on a templated control. In case of a Button, it is the Content property that you want to bind.
Implements a markup extension that supports the binding between the value of a property in a template and the value of some other exposed property on the templated control.
<TextBlock Text="{TemplateBinding Content}"
Margin="3 0" HorizontalAlignment="Center" VerticalAlignment="Center"/>
A simple Binding will resolve a property on the current data context. You can also make this work, but you need to specify a RelativeSource using TemplatedParent.
TemplatedParent - Refers to the element to which the template (in which the data-bound element exists) is applied. This is similar to setting a TemplateBindingExtension and is only applicable if the Binding is within a template.
<TextBlock Text="{Binding Content, RelativeSource={RelativeSource TemplatedParent}}"
Margin="3 0" HorizontalAlignment="Center" VerticalAlignment="Center"/>
Please note that in this scenario a TemplateBinding is sufficient, as it is only one way. In a two-way binding you would have to use the variant using RelativeSource and TemplatedParent.
A TemplateBinding is an optimized form of a Binding for template scenarios, analogous to a Binding constructed with {Binding RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}. A TemplateBinding is always a one-way binding, even if properties involved default to two-way binding. Both properties involved must be dependency properties. In order to achieve two-way binding to a templated parent use the following binding statement instead {Binding RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay, Path=MyDependencyProperty}.
I'm using progress bar for gantt chart in my project and is going good. Now I need to show time and details when mouse is placed over it without click. Is it possible and have anyone done something similar before?
You can set a StackPanel for the ToolTip to show both Time and details when the mouse is over.By default, when the mouse over the control, and its ToolTip will pop-up, the below is my processbar with tooltip:
<ProgressBar x:Name="MyBar" Width="200" Height="20" Value="60">
<ProgressBar.ToolTip>
<ToolTip>
<StackPanel>
<TextBox Text="Here is the details" Background="LightBlue" Height="50" Width="120"></TextBox>
<TextBlock Text="{Binding Source={x:Static sys:DateTime.Now}}" Background="Azure" Height="50" Width="120"/>
</StackPanel>
</ToolTip>
</ProgressBar.ToolTip>
</ProgressBar>
The result picture is like:
This is for Tooltip:
Just write:
<ProgressBar Minimum="0" Maximum="100" Value="75" Tooltip="Your desired text" />
or bind your text:
<ProgressBar Minimum="0" Maximum="100" Value="75" Tooltip="{Binding, path=YourText}" />
For hover use IsMouseOver property:
<ProgressBar Minimum="0" Maximum="100" Value="75">
<ProgressBar .Style>
<Style TargetType="ProgressBar">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
--your desired code--
</Trigger>
</Style.Triggers>
</Style>
</ProgressBar.Style>
</ProgressBar>
I am trying to show one collapsed stackpanel on button click, but I'm having problems so I tried reverse my thoughts and I was able to collapse an visible stackpanel. But unfortunately I was unable to implement the behavior I want, show an collapsed stack panel on button click. To the code :D
XAML
<Button x:Name="sentButton" Content="Add Friend" Style="{DynamicResource FlatButtonStyle}" Margin="493,0,0,0" HorizontalAlignment="Left" Width="106"/>
<StackPanel Style="{DynamicResource stackCollapsed}" Visibility="Collapsed">
<Label Content="Invite Friends" FontWeight="Bold" Margin="0,0,477,0" Height="32" />
<StackPanel Orientation="Horizontal" Margin="26,0,0,0">
<Label Content="Enter your friend's email" Width="222" Height="25" />
<TextBox Text="{Binding Email, UpdateSourceTrigger=PropertyChanged}" Style="{DynamicResource MyTextBox}" x:Name="textBoxEmail" Width="298"/>
<Button x:Name="button1" Content="Send" Command="{Binding AddCommand}" Width="77" Style="{DynamicResource FlatButtonStyle}" Margin="20,0,0,0"/>
</StackPanel>
</StackPanel>
Styles
<!-- Style Collapsed-->
<Style x:Key="stackCollapsed" TargetType="StackPanel">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=sentButton,Path=IsPressed}" Value="true">
<Setter Property="StackPanel.Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
Instead of Button use ToggleButton and bind StackPanel.Visibility to ToggleButton.IsChecked property via BooleanToVisibilityConverter converter
<ToggleButton x:Name="sentButton" Content="Add Friend" Margin="493,0,0,0" HorizontalAlignment="Left" Width="106"/>
<StackPanel Visibility="{Binding ElementName=sentButton, Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter}}">
<Label Content="Invite Friends" FontWeight="Bold" Margin="0,0,477,0" Height="32" />
<StackPanel Orientation="Horizontal" Margin="26,0,0,0">
<Label Content="Enter your friend's email" Width="222" Height="25" />
<TextBox Text="{Binding Email, UpdateSourceTrigger=PropertyChanged}" x:Name="textBoxEmail" Width="298"/>
<Button x:Name="button1" Content="Send" Command="{Binding AddCommand}" Width="77" Margin="20,0,0,0"/>
</StackPanel>
</StackPanel>
where converter is defined as below
<Window.Resources>
<ResourceDictionary>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</ResourceDictionary>
</Window.Resources>
The problem is the Visibility property in the <StackPanel> tab takes a higher precedence than anything set in a Style or Trigger, so the Trigger never gets applied. See the Dependency Property Precedence List for more details.
To fix your current solution, move the Visibliity property out of the <StackPanel> tag and into your Style, like this :
<Style x:Key="stackCollapsed" TargetType="StackPanel">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=sentButton,Path=IsPressed}" Value="true">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
<StackPanel Style="{DynamicResource stackCollapsed}">
...
</StackPanel>
That said, I would personally recommend something like a Toggle Button with the StackPanel.Visibility bound to the ToggleButton.IsChecked, like this answer suggests.
I solved set the Children to null
stackPanel.Children.Clear();
this work if you need to show / hide the panel the first time, it doesn't work if you need to do runtime
Simple as Stackpanel.Visibility = Visibility.Collapsed.
i got a DataTemplate for a listboxitem and i want to create a triger , so when a user click an item the background will change and also the label
my code:
<Window.Resources>
<Style x:Key="RoundedItem" TargetType="ListBoxItem">
<EventSetter Event="MouseDoubleClick" Handler="listViewItem_MouseDoubleClick" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border Name="ItemBorder" CornerRadius="10" BorderBrush="Black" BorderThickness="1" Margin="1" Background="Transparent">
<Label Name="ItemLabel" Foreground="Red" >
<ContentPresenter />
</Label>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="ItemBorder" Property="Background" Value="DeepSkyBlue" />
<Setter TargetName="ItemLabel" Property="Foreground" Value="Orange" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<DataTemplate x:Key="TitleTemplate" DataType="models:Title" >
<StackPanel>
<Image Source="{Binding ThumbFilePath}" Width="50" HorizontalAlignment="Center"/>
<Label Content="{Binding Name}" HorizontalAlignment="Center" />
<TextBlock Text="{Binding Description}" HorizontalAlignment="Center" TextWrapping="Wrap" Padding="5,5,5,5"/>
</StackPanel>
</DataTemplate>
</Window.Resources>
What happend is that the TextBlock change his color and not the label..
anyone know why ?
Thanks.
The TextBlock inherits the Foreground definition from its parents in the visual tree. The Label, on the other hand, defines the Foreground in its default style.
Your approach is "non-WPF-like" - you shouldn't wrap the ContentPresenter in a Label control.
The right approach depends on whether you want all text in the item to change its Foreground, or just the label?
[In both cases, there's no apparent benefit to using a Label in the data template - so I'll assume that the label is changed to TextBlock.]
If the answer to the above question is that all text should be changed: in the ControlTemplate of the ListBoxItem, in the trigger for IsSelected, from the seccond setter remove TargetName="ItemLabel" so the final setter is:
<Setter Property="Foreground" Value="Orange" />
This will change the foreground of the item that will affect the foreground of both TextBlocks in the data template.
If you want to affect just one of the TextBlocks:
1. remove the setter for the foreground from the control template
2. add a trigger to your data template:
<DataTemplate>
<StackPanel>
<Image .../>
<TextBlock x:Name="Text01" ..../>
<TextBlock x:Name="Text02" ..../>
</StackPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}" Value="True">
<Setter TargetName="Text01" Property="Foreground" Value="Orange"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
Side note: if you have to use Label control in your data template, bind its Foreground property to the Foreground of the list box item, like so:
<Label Foreground="{Binding Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}"....../>
If this doesn't help, it means that your list box item inherits its foreground, so use:
<Label Foreground="{Binding TextElement.Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}"....../>
I want to tack on to this that I was experiencing a similar problem where I'd added a ListBox.ItemTemplate to my ListBox, and the styling then did not apply to the text anymore.
What I was doing was trying to display a list of languages (CultureInfo) for the user to select from, however I wanted the native names to display, not the English name. For some reason, not all languages have their native names capitalized in their CultureInfo, and NativeName is the only instance of their name, so I needed to apply a function to the CultureInfo.NativeName to capitalize the names myself. To accomplish this, I added the ItemTemplate with a Data Template inside, on which I applied a converter.
<ListBox IsSynchronizedWithCurrentItem="True" VerticalAlignment="Center" MinHeight="200" x:Name="cbLanguages"
ItemsSource="{Binding Path=SupportedCultures, Mode=OneWay, Source={StaticResource CultureResourcesDS}}"
FontSize="24" HorizontalAlignment="Stretch" Width="300" Margin="10"
Style="{DynamicResource ListBoxTemplate}" ItemContainerStyle="{DynamicResource ListBoxItemStyle}">
<ListBox.ItemTemplate>
<DataTemplate>
<Label Content="{Binding Converter={StaticResource NativeNameConverter}}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
After a while of searching, I came across XAMeLi's answer here, and changed the Label I'd put in the DataTemplate to a TextBox, and the ListBoxItemStyle I'd created worked again.
Basically, Labels and TextBoxes have different traits that can be exploited, or can cause annoying issues in this case. Here's a good explanation with some examples of the differences: http://joshsmithonwpf.wordpress.com/2007/07/04/differences-between-label-and-textblock/
On the internet I found many examples of styling a complete column or complete row in a listview.
I need to be able to dynamically style individual cells in the listview. How can I access the properties of individual items in a row?
If you've got a finite number of properties in your data objects that you want to use to style your items, you can create data templates and styles, and use data triggers to switch between them. I've used something like this to alter the appearance of data objects in a list based on if they are "active/inactive" and to create a collapsed/expanded version of the object based on whether it's selected or not.
You can also use converters (built-in or custom) to get some effects easily. For example, I used a built-in boolean to visibility converter to hide/unhide the combobox/textblock in my TaskSelectedTemplate based on if the object's IsActive member.
<DataTemplate x:Key="TaskSelectedTemplate">
<Grid Margin="4">
...
<Border Grid.Row="0" Grid.Column="0" Grid.RowSpan="4" Margin="0 0 4 0"
BorderThickness="0"
CornerRadius="2">
<Border.Background>
<MultiBinding Converter="{StaticResource ActiveToColor}">
<Binding Path="."/>
<Binding Path="IsActive"/>
<Binding Path="IsPaused"/>
</MultiBinding>
</Border.Background>
</Border>
<StackPanel Grid.Row="0" Grid.Column="1"
Orientation="Horizontal"
Margin="0 2">
<ComboBox ItemsSource="{Binding Source={StaticResource TaskTypes}}"
SelectedItem="{Binding Type}"
Text="{Binding Type}"
Visibility="{Binding IsActive, Converter={StaticResource BoolToVis}}"/>
<TextBlock Text="{Binding Type}"
FontWeight="Bold"
Visibility="{Binding IsActive, Converter={StaticResource InvBoolToVis}}"/>
<TextBlock Text=" task"/>
</StackPanel>
...
</Grid>
</DataTemplate>
<DataTemplate x:Key="TaskNotSelectedTemplate">
<Grid Margin="4">
...
<Border Grid.Row="0" Grid.Column="0" Grid.RowSpan="4" Margin="0 0 4 0"
BorderThickness="0"
CornerRadius="2">
<Border.Background>
<MultiBinding Converter="{StaticResource ActiveToColor}">
<Binding Path="."/>
<Binding Path="IsActive"/>
<Binding Path="IsPaused"/>
</MultiBinding>
</Border.Background>
</Border>
<TextBlock Grid.Row="0" Grid.Column="1"
Text="{Binding Type}"/>
<TextBlock Grid.Row="0" Grid.Column="2"
TextAlignment="Right">
<Run Text="{Binding Length.TotalMinutes, StringFormat='0', Mode=OneWay}"/>
<Run Text=" min"/>
</TextBlock>
<TextBlock Grid.Row="0" Grid.Column="3"
TextAlignment="Right">
<Run Text="{Binding TimesPerformed, Mode=OneWay}"/>
<Run Text=" tasks"/>
</TextBlock>
</Grid>
</DataTemplate>
<Style x:Key="ContainerStyle" TargetType="{x:Type ListBoxItem}">
<!--this part changes the selected item highlight color-->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border Name="Border">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="Border"
Property="Background" Value="#2000BFFF">
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<!--this part causes selected task to expand-->
<Setter Property="ContentTemplate" Value="{StaticResource TaskNotSelectedTemplate}"/>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="ContentTemplate" Value="{StaticResource TaskSelectedTemplate}"/>
</Trigger>
</Style.Triggers>
</Style>
For more complex scenarios, you might want to look at DataTemplateSelector. I've never used it, but it seems like it might be ideal if you've got a lot of data templates to juggle.
Generally speaking, you shouldn't need this. Assuming you are using GridView, you should be able to use CellTemplate or CellTemplateSelector of your GridViewColumns.
If you really want to access specific cells, I think there is no clean way, you'd be better using DataGrid (from .Net 4 or WPF toolkit for .Net 3.5). With that, you can do something like this:
((TextBlock)datagrid.Columns[1].GetCellContent(m_specificItem)).Background = Brushes.Red