Silverlight: Adding ChangePropertyAction to DataTemplate - silverlight

I was playing around, experimenting and googling this for the last hour and cannot figure out the problem. Basically, I have a listbox, each item has textblock and checkbox. I need to change text of textblock to green next to the checked checkbox. The code below is the best that I could come up with, but it doesn't work. Any help is appreciated.
<DataTemplate x:Key="ListBoxTemplate">
<Grid
Width="80">
<TextBlock
x:Name="textBlock"
HorizontalAlignment="Left"
Text="{Binding Data, Converter={StaticResource DataConverter}}"
Foreground="#FF859FAF"
FontSize="12"
TextWrapping="Wrap"
Width="50"
Margin="0"
Grid.Row="10" />
<CheckBox
x:Name="Btn6"
IsChecked="{Binding IsSelected, Mode=TwoWay}"
Cursor="Hand"
Padding="0"
HorizontalAlignment="Right"
Height="32"
VerticalAlignment="Bottom"
RenderTransformOrigin="0.5,0.5"
Width="26"
d:LayoutOverrides="GridBox">
<i:Interaction.Triggers>
<i:EventTrigger
EventName="textBlock">
<ei:ChangePropertyAction
TargetName="textBlock"
TargetObject="{Binding ElementName=textBlock}"
PropertyName="Width"
Value="100">
</ei:ChangePropertyAction>
<i:InvokeCommandAction
Command="{Binding SelectDataCommand, Source={StaticResource ControlViewModel}}"
CommandName="SelectDateRangeCommand"
CommandParameter="{Binding}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</CheckBox>

(sorry for my bad english)
This do not exactly answer your question but an easy alternative would be to bind IsSelected with the TextBox.Foreground and create a converter that return a SolidColorBrush green when the value is true

Related

TemplateBinding as InvokeCommandAction CommandParameter not working?

I'm trying to write a reusable template for a control I want to use several times in my window. In it I have some commands with CommandParameter. The CommandParameter is an object I want to pass via the "Tag" property of this template.
For the "MenuItem" CommandParameter and the StackPanel "DataContext" this is working just fine. But for the "MouseDown" event (or "PreviewMouseDown", I tried both) via InvokeCommandAction I'm only getting a null as parameter. It is firing the command and calls the right method, but the parameter is always null.
Here my Xaml (shortend):
<Window.Resources>
<ControlTemplate x:Key="FavControl" TargetType="ContentControl">
<StackPanel>
<StackPanel.ContextMenu>
<ContextMenu IsEnabled="{Binding FavContextMenuEnabled}">
<MenuItem Header="Bearbeiten"
Command="{Binding FavContextMenuEditCmd}"
CommandParameter="{TemplateBinding Tag}" />
<MenuItem Header="Löschen"
Command="{Binding FavContextMenuDeleteCmd}"
CommandParameter="{TemplateBinding Tag}" />
<Separator IsEnabled="{Binding UserisDev}" />
<MenuItem Header="Entwicklung"
Command="{Binding FavContextMenuStartDevCmd}"
CommandParameter="{TemplateBinding Tag}"
IsEnabled="{Binding UserisDev}" />
<MenuItem Header="Starte Objekt"
Command="{Binding FavContextMenuRunObjectCmd}"
CommandParameter="{TemplateBinding Tag}"
IsEnabled="{Binding UserisDev}" />
</ContextMenu>
</StackPanel.ContextMenu>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDown">
<i:InvokeCommandAction Command="{Binding FavoriteClickCmd}" CommandParameter="{TemplateBinding Tag}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<StackPanel Orientation="Vertical" DataContext="{TemplateBinding Tag}">
<Image Source="{Binding FavImage, UpdateSourceTrigger=PropertyChanged,Mode=OneWay}"
HorizontalAlignment="Center" VerticalAlignment="Center" Height="70" Width="70" />
<TextBlock Text="{Binding Description}" HorizontalAlignment="Center" />
</StackPanel>
</StackPanel>
</ControlTemplate>
</Window.Resources>
<!-- ... -->
<ContentControl Grid.Row="0" Grid.Column="0" Template="{StaticResource FavControl}" Tag="{Binding FavoriteArray[0]}" />
<ContentControl Grid.Row="0" Grid.Column="1" Template="{StaticResource FavControl}" Tag="{Binding FavoriteArray[1]}" />
<ContentControl Grid.Row="0" Grid.Column="2" Template="{StaticResource FavControl}" Tag="{Binding FavoriteArray[2]}" />
<!-- ... -->
I need this parameter in the code behind method to know which object to work with. So, how can I pass this object? Why is the TemplateBinding not working? Can anybody tell me, what I'm doing wrong?
P.S.: Sorry for errors, english is not my native language :)
Instead of TemplateBinding, use a RelativeSource binding to TemplatedParent.
<b:InvokeCommandAction Command="{Binding FavoriteClickCmd}"
CommandParameter="{Binding Tag, RelativeSource={RelativeSource TemplatedParent}}" />

WPF Textboxes and Textblocks not rendered

I have a strange behavior of my application on some computers (it only happens at some customer pcs, i can't reproduce it on my machines).
I have an application to enter and view production scrap data. Every column is an control on it's own. The Expanders are accordion Controls from the WPF Toolkit.
Sometimes Textblocks are not visible:
When the bug happens to Textboxes, they are not even consuming any space:
This is the Datatemplate for the Content of the Accordion Item:
<DataTemplate x:Key="YieldAccContent" DataType="Models:Cell">
<DataTemplate.Resources>
<DataTemplate x:Key="It1">
<StackPanel >
<Label BorderBrush="{x:Static SystemColors.ControlLightBrush}" Padding="1" Height="22" BorderThickness="1" Content="{Binding Value}" Visibility="{Binding Cell.CellGroup.ParentMeasurement.IsEnabled, Converter ={StaticResource boolTovisinv}}"/>
<controls:NumberTextbox Text="{Binding Value, Converter ={StaticResource EmptyStringToNullConverter}, UpdateSourceTrigger=PropertyChanged}" Height="22" Width="80" Visibility="{Binding IsEnabledAndBad, Converter ={StaticResource boolTovis}}" Background="AliceBlue">
<i:Interaction.Triggers>
<i:EventTrigger EventName="LostFocus" >
<cmd:EventToCommand Command="{Binding MeasurmentViewModel.LostFocusCommand, Mode=TwoWay, Source={StaticResource Locator}}" PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
</controls:NumberTextbox>
<toolkit:MaskedTextBox Mask ="-99999999" Value="{Binding Value, Converter ={StaticResource EmptyStringToNullConverter}, UpdateSourceTrigger=PropertyChanged}" PromptChar=" " Height="22" Width="80" Visibility="{Binding IsEnabledAndGood, Converter ={StaticResource boolTovis}}" IncludeLiterals="True" IncludePrompt="False" Background="AliceBlue" ValueType="{x:Type sys:Int64}" GotFocus="MaskedTextBox_GotFocus_1" SelectionChanged="MaskedTextBox_SelectionChanged_1">
</toolkit:MaskedTextBox>
</StackPanel>
</DataTemplate>
</DataTemplate.Resources>
<StackPanel >
<Label BorderBrush="{x:Static SystemColors.ControlLightBrush}" BorderThickness="1" Padding="1" Height="22" Width="160" Content="{Binding YieldInput}" Background="Moccasin"/>
<Label BorderBrush="{x:Static SystemColors.ControlLightBrush}" BorderThickness="1" Padding="1" Height="22" Width="160" Content="{Binding YieldOutput}" Background="Moccasin"/>
<Label BorderBrush="{x:Static SystemColors.ControlLightBrush}" BorderThickness="1" Padding="1" Height="22" Width="160" Content="{Binding Yield}" Background="Moccasin"/>
<ItemsControl ItemsSource="{Binding Stations}" ItemTemplate="{StaticResource It1}">
</ItemsControl>
</StackPanel>
</DataTemplate>
This is the Accordion Item itself:
<System_Windows_Controls:Accordion ContentTemplate="{StaticResource Cont}" ItemTemplate="{StaticResource Head}" ItemsSource="{Binding Cells}" SelectedIndex="{Binding SelectedAccItem, Mode=TwoWay}" SelectionMode="{Binding MeasurmentViewModel.SelectionMode, Source={StaticResource Locator}}" HorizontalAlignment="Stretch" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectedItemsChanged" >
<cmd:EventToCommand Command="{Binding MeasurmentViewModel.SelectedItemsChangedCommand, Mode=TwoWay, Source={StaticResource Locator}}" PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
</System_Windows_Controls:Accordion>
What could be the cause of this behavior?
Going by your description about the missing TextBoxes not taking any space, I can only assume that you have a Trigger or Converter attached to their Visibility property. If you put a break point in the Converter that is attached to the offending TextBox, then you can debug whether this is the cause quite easily. I assume that the bool value(s) that you are binding to in the Visibility property is not being set correctly... please check whether this is true.

WPF MVVM customizing ListView cell to insert hyperlink and change text color

I have a GridView cell in a ListView that is defined as a TextBlock and bound to a string on my ViewModel. I want to be able to change parts of the text into hyperlinks and part into different colors programatically.
Here is the XAML for the GridView cell:
<GridViewColumn.CellTemplate>
<DataTemplate>
<Border BorderThickness="2" BorderBrush="#dfdfdf" HorizontalAlignment="Stretch">
<TextBlock Text="{Binding Data}" Margin="3"/>
</Border>
</DataTemplate>
</GridViewColumn.CellTemplate>
And here's what it looks like at the moment:
An example of the text that is bound would be:
<color:#ff0000>Test item</color>
Test item 2
<link:http://www.google.com>Test hyperlink</link>
I have no problem with the regex to parse the bound text and pull out the required information but how would I go about changing the TextBlock into different colors and add a hyperlink?
Thanks in advance
You can put multiple Run elements inside a TextBlock and style then however you like.
Here is an example with a working hyperlink which even supports MVVM :)
<GridViewColumn.CellTemplate>
<DataTemplate>
<Border BorderThickness="2" BorderBrush="#dfdfdf" HorizontalAlignment="Stretch">
<TextBlock Margin="3">
<Run Text="{Binding Data}" />
<Run Text="Some more data" Background="Red" />
<Run Text="Click Me" Foreground="Blue" TextDecorations="Underline" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDown">
<local:EventToCommand Command="{Binding LinkClickCommand, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Run>
</TextBlock>
</Border>
</DataTemplate>
</GridViewColumn.CellTemplate>
Note:
The Interaction.Triggers are from System.Windows.Interactivity and the EventToCommand from MVVMLight.
Similar to Blachshma's answer, but using a hyperlink right in there with the Run objects:
<TextBlock>
<Run Text="{Binding Data}" />
<Run Text="Some more data" Background="Red" />
<Hyperlink Command="{Binding Path=Command}">
<TextBlock Text="{Binding Path=Text}"/>
</Hyperlink>
</TextBlock>
Clearly I have a Command and Text properties to bind to for the hyperlink. Will look exactly the same, but will also respond to the command's CanExecute predicate (hyperlinks go grey).

WPF ComboBox Show Alternate Text

I am trying to change the text of a WPF combobox button to something custom that isn't an actual selected item. The combobox control is setup with a custom datatemplate that allows it to contain checkboxes and what I'm trying to do is display "None Selected", [SelectedItem.Text] or "Multiple Selected" depending on whether zero items are checked, one is checked or more than one is checked. I found one solution on here that involved adding a new textblock instance that could display this text and then set the text of it to what I want to display. This works great until someone clicks and area next to the label of the checkbox and the text of that item shows up underneath my custom textblock causing weird overlap issues.
My assumption is a converter of some kind (which can replace the custom textblock as far as I'm concerned - no preference there), but I'm not entirely sure how to apply it. Here is my XAML thus far:
<Grid Grid.Row="4" Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ComboBox x:Name="SubjectMatterList" Style="{StaticResource ComboBox}" ItemsSource="{Binding SubjectMatters}" Visibility="{Binding AdjunctListVisibility}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" MinWidth="125" MaxWidth="125" Margin="6">
<CheckBox Content="{Binding Name}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Checked">
<mvvm:EventToCommand Command="{Binding DataContext.SubjectMatterSelectedCommand, ElementName=GradeLevelList}" CommandParameter="{Binding}" />
</i:EventTrigger>
<i:EventTrigger EventName="Unchecked">
<mvvm:EventToCommand Command="{Binding DataContext.SubjectMatterDeselectedCommand, ElementName=GradeLevelList}" CommandParameter="{Binding}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</CheckBox>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBlock IsHitTestVisible="False" x:Name="SelectedSubjectMatter" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10" Padding="10,6,0,6" Text="{Binding ComboBoxSubjectMatterText}" Visibility="{Binding AdjunctListVisibility}" />
<TextBlock Text="{Binding SelectedSubjectMatterText}" Grid.Row="1" Margin="10" Visibility="{Binding SubjectMatterSelectedVisibility}" />
http://blogs.microsoft.co.il/blogs/justguy/archive/2009/01/19/wpf-combobox-with-checkboxes-as-items-it-will-even-update-on-the-fly.aspx

Item rendered via a DataTemplate with any Background Brush renders selection coloring behind item

I have a ListBox which uses a DataTemplate to render databound items. The XAML for the datatemplate is as follows:
<DataTemplate x:Key="NameResultTemplate">
<WrapPanel x:Name="PersonResultWrapper" Margin="0" Orientation="Vertical" Background="{Binding Converter={StaticResource NameResultToColor}, Mode=OneWay}" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDown">
<cmd:EventToCommand x:Name="SelectPersonEventCommand" Command="{Binding Search.SelectedPersonCommand, Mode=OneWay, Source={StaticResource Locator}}" CommandParameter="{Binding Mode=OneWay}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<TextBlock x:Name="txtPersonName" TextWrapping="Wrap" Margin="0" VerticalAlignment="Top" Text="{Binding PersonName}" FontSize="24" Foreground="Black" />
<TextBlock x:Name="txtAgencyName" TextWrapping="Wrap" Text="{Binding AgencyName}" HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="0" FontStyle="Italic" Foreground="Black" />
<TextBlock x:Name="txtPIDORI" TextWrapping="Wrap" Text="{Binding PIDORI}" HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="0" FontStyle="Italic" Foreground="Black" />
<TextBlock x:Name="txtDescriptors" TextWrapping="Wrap" Text="{Binding DisplayDescriptors}" Margin="0" VerticalAlignment="Top" Foreground="Black"/>
<Separator Margin="0" Width="400" />
</WrapPanel>
</DataTemplate>
Note that there is a value converter called NameResultToColor which changes the background brush of the rendered WrapPanel to gradient brush depending on certain scenarios.
All of this works as I'd expect, except when you click on any of the rendered ListBox items. When you click one, there is only the slightest sign of the selection coloring (the default bluish color). I can see a trace bit of it underneath my gradient-brushed item. If I reset the background brush to "no brush" then the selection rendering works properly. If I set the background brush to a solid color, it also fails to render as I'd expect.
How can I get the selection coloring to be on top? What is trumping the selection rendering?
The problem is that your item's template is being drawn over the selection being drawn by the ListBoxItem. If you want to ensure that the color is kept, you can add a DataTrigger to set the background of the WrapPanel to null when the item is selected:
<DataTemplate x:Key="NameResultTemplate">
<WrapPanel x:Name="PersonResultWrapper">
...
</WrapPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}" Value="True">
<Setter TargetName="PersonResultWrapper" Property="Background" Value="{x:Null}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>

Resources