CustomUserControl Double Click Event in ControlTemplate in WPF - wpf

In WPF I created a CustomUserControl with DoubleClick event handler. I am using this control inside ControlTemplate in this way:
<xcdg:DataCell FieldName="." Template="{StaticResource myTemplate}">
</xcdg:DataCell>
And also this my ControlTemplate:
<ControlTemplate x:Key="myTemplate" TargetType="xcdg:DataCell">
<uicontrols:MyCustomControl Tag="{Binding ID}" Margin="0" Height="140" Width="150" DoubleClick="ctrl_DoubleClick">
</ControlTemplate>
DoubleClick event handler is not working inside the ControlTemplate. what is the problem and what is the best solution?

I found out my answer. rather than using extra template in DateCell. I used inline template.
<xcdg:DataCell FieldName=".">
<xcdg:DataCell.Template>
<ControlTemplate>
// your template code. here the event of my controls are working.
</ControlTemplate>
</xcdg:DataCell.Template>
</xcdg:DataCell>

Related

How do I properly set this button's binding to the parent ListView ItemsControl?

I have a custom button set up inside a ListView ItemTemplate. The Listview's ItemSource is bound to a collection of items, pretty standard. I have a few labels in the listview as well, and everything works fine except the button.
Binding the button to one of the properties won't work at all using {Binding buttonName} but it will sort of work if I use {Binding Items/buttonName, ElementName=listView} - the only problem is, when I do it this way, every single button in that listView will have the exact same buttonName.
Now the issue stems from my custom button's DataContext being set to Self; unfortunately, it has to be set to Self because the custom style I'm using needs this. If I try to change the button to a UserControl instead (with the button as a child, and the DataContext set on that), then I can't use the Command property of the button for some reason.
Here's a simplified version of my ListView making use of the custom button:
<ListView x:Name="listView" ItemsSource="{Binding MyPeopleData}">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Label Content="{Binding PersonName}"/>
<ct:RevealButton Content="{Binding Items/recommendation, ElementName=listView}"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
As I said above, this will make every item in the listview use the same recommendation property rather than using it's own one.
If I try to use
<ct:RevealButton Content="{Binding recommendation}"/>
It just won't work, which makes sense given the DataContext of the custom button, which is below:
<Button x:Class="RevealButton" Width="{Binding Width}" Height="{Binding Height}" Background="{Binding ButtonBackground}" DataContext="{Binding RelativeSource={RelativeSource Self}}" Style="{DynamicResource ButtonRevealStyleC}" mc:Ignorable="d">
<Button.ContentTemplate>
<DataTemplate>
<ContentPresenter Content="{TemplateBinding Content}" />
</DataTemplate>
</Button.ContentTemplate>
</Button>
So this ended up being an XY Problem. Because the modified style I was using had a poorly bound property, it was failing when the parent control didn't have a DataContext set to self.
This is what it was:
<SolidColorBrush Opacity="0.8" Color="{Binding ButtonBackground.Color}" />
And ButtonBackground was a dependency property exposed by my custom Button, so binding the style in this way meant it only worked if the Button's context was itself. Changing it to this:
<SolidColorBrush Opacity="0.8" Color="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ButtonBackground.Color}" />
Fixed the DataContext dependency, which in turn fixes the heirarchy of problems above.

Triggers, commands not firing in custom ListBox's ItemTemplate

I've got a custom ListBox control with a style set up in my Themes/Generic.xaml. I then have a button in the ListBox's ItemTemplate, and it's Click event isn't firing and I've got no idea why. Same goes for the button's Commands (I'm confident the Command issue isn't DataContext related) and interaction triggers. While attempting to debug, I noticed that using the default ListBox instead of my own stopped the problem, but I need to use the custom control.
This is essentially what I've got (fluff removed for brevity). The button:
<controls:CustomListBox>
<ListBox.ItemTemplate>
<DataTemplate>
<Button Click=MyHandler/>
</DataTemplate>
</ListBox.ItemTemplate>
</controls:CustomListBox>
And the custom control's style in Themes/Generic:
<Style TargetType="{x:Type controls:CustomListBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls:CustomListBox}">
<Border>
<ScrollViewer Focusable="false" Padding="{TemplateBinding Padding}">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
How can I get this event to fire?
I think this should probably be a usercontrol rather than a custom control.
Are you really going to change the template out of this for something else?
If you use an event handler like that then how are you planning on using the delegate? It's a very inflexible way of working you're headed in.
You mentioned command, which is probably rather more like it.
If you use a button in an item template with a command bound like
<Button Command="{Binding RowCommand}"
Then the datacontext of that Button is the content of the row.
If you bind ItemsSource to a collection Items of ItemVM then it's looking in the ItemVM that is presented to that row.

ControlTemplate for adding UIElements to original control

I want to add an exclamation mark Image to the left of the built-in TextBox and make it visible whenever the TextBox Validation.HasError attached property is true, otherwise hide it.
How can I use ControlTemplate to add the Image without having re-bind all the TextBox properties?
<StackPanel>
<StackPanel.Resources>
<ControlTemplate x:Key="TextBoxWithIndicator" TargetType="{x:Type TextBox}">
<StackPanel Orientation="Horizontal">
<!-- Re-bind {Binding Path=Property}, including some that I may miss -->
<TextBox Text="{TemplateBinding Text}" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}"/>
<Image Source="resources/exclaim.png" Visibility="{TemplateBinding Validation.HasError}"/>
</StackPanel>
</ControlTemplate>
</StackPanel.Resources>
<TextBox Template="{StaticResource TextBoxWithIndicator}" Width="120">Happy Go Lucky</TextBox>
</StackPanel>
Note The preceding block of code represents my futile effort in WPF so far. It is probably also wrong on several counts, e.g. probably need a ValueConverter for Visibility <--> Validation.HasError; Setting Width="120" on TextBox seems to adjust the StackPanel width instead of TextBox width despite the TemplateBinding, etc.
I would suggest looking into Adorners. These are special FrameworkElements that are rendered in a special Adorner Layer on top of visual elements, and are intended to provide visual cues to the user.
The above link provides a summary of Adorners as well as an example of a Custom Adorner.

Binding the button Content to the userControl Content

I have some userControl that contain simple button.
I want to bind the button Content to the userControl Content - How to do it?
Set a name for the user control (for example x:Name="self") and in the Button
<Button Content={Binding ElementName=self}" />
Do you mean this or something else?
If the Button is inside the UserControl it is part of the UserControl's Content and can't recursively contain itself. The whole purpose of a UserControl is that you're explicitly defining a fixed set of Content. If you want variable Content then you should use a templated ContentControl something like this:
<ContentControl Content="{Binding SomeVariableValue}">
<ContentControl.Template>
<ControlTemplate TargetType="{x:Type ContentControl}">
<Border>
<!-- Other content from your user control -->
<Button Content="{TemplateBinding Content}"/>
</Border>
</ControlTemplate>
</ContentControl.Template>
</ContentControl>

Exposing a sub-control in a UserControl for use in XAML

I have a UserControl that contains a TreeView. I want the user to be able to set the properties of the inner TreeView control via XAML and I'm not sure how to do that.
I've tried creating a public property on the UserControl to the TreeView, but that only allows me to set a SelectedItemChanged trigger.
I'd like to do something like:
<ExampleUserControl>
<ExampleUserControl.TreeView.ItemTemplate>
...
</ExampleUserControl.TreeView.ItemTemplate>
</ExampleUserControl>
Or:
<ExampleUserControl TreeView.ItemsSource="{Binding Foo}" />
I would prefer not to create properties in the UserControl for each TreeView property, and I don't want to force the user to define the control in C#.
As for passing multiple properties to the child control in your user control, you can always expose a Style property.
ie ChildStyle
For the ItemsSource unless you use [Josh Smith's Element Spy / Data Context Spy / Freezable][1] trick, you will have a disconnect on DataContexts.
So either you employ those tricks or simply have 2 properties.
1) the ItemsSource
2) the ChildStyle
The xaml ends up...
<ChildTreeAnswer:MyControl ItemsSource="{Binding Items}">
<ChildTreeAnswer:MyControl.ChildStyle>
<Style>
<Setter Property="ItemsControl.ItemTemplate">
<Setter.Value>
<DataTemplate>
<Border BorderBrush="Black"
BorderThickness="1"
Margin="5">
<TextBlock Text="{Binding }" />
</Border>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</ChildTreeAnswer:MyControl.ChildStyle>
</ChildTreeAnswer:MyControl>
Then in your user control do... (I used a listbox for simplicity sake)
<ListBox ItemsSource="{Binding ItemsSource}"
Style="{Binding ChildStyle}" />

Resources