Not all content is clickable on custom control derived from button - wpf

iv'e got a "Cube" (Dice) control which derives from Button
Cube :
public class Cube : Button
{
public Cube()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(Cube), new FrameworkPropertyMetadata(typeof(Cube)));
}
...... // Stuff
}
Template (In general):
<ControlTemplate TargetType="{x:Type local:Cube}" x:Key="CubeControlTemplate">
<Border>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="40"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border>
<Grid>
.......
</Grid>
</Border>
<Border Grid.Column="2">
<Grid>
.......
</Grid>
</Border>
<Grid>
</Border>
</ControlTemplate>
what it looks like :
the yellow marking shows that it is clickable only behind the Content , only if you really target your click where the Button is "Hidden" ..
any ideas why this happens ?

Without a Background mouse events will not be catched. Give your outer Border a transparent Color:
<ControlTemplate TargetType="{x:Type local:Cube}" x:Key="CubeControlTemplate">
<Border Background="Transparent">
.......
</Border>
</ControlTemplate>

Please check that you are not trying to click on an element that has a Null background. Hit testing requires a Brush to be set.
If your Border or your Grid has a Null background try setting it to Transparent.
If you are still having issues try debugging with Snoop.
http://snoopwpf.codeplex.com/

Related

How can I get controls inside the custom control?

I made a Custom Control, here is the XAML:
<Style TargetType="{x:Type local:Sheet}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:Sheet}">
<Grid Grid.IsSharedSizeScope="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="71"></ColumnDefinition>
<ColumnDefinition Width="auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="18"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
</Grid.RowDefinitions>
<Border Background="{TemplateBinding Background}" Grid.Column="1" Grid.Row="1"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}" VerticalAlignment="{TemplateBinding VerticalAlignment}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}">
<Grid x:Name="G">
<Border Background="#59217346"></Border>
</Grid>
</Border>
<Button Background="#e6e6e6" BorderBrush="#999999" BorderThickness="0,0,1,1" Visibility="Collapsed">◢</Button>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I need to access the Grid which x:Name="G" to add&remove its children.
I found a topic about this:Access children of Custom Control wpf c#
It suggests using a Dependency Property. However, I can't bind the Children of the Grid yet.
There is another solution by using a VisualTreeHelper to get the Grid directly.
Meanwhile, the VisualTreeHelper can only get the child while the control is completely loaded, or it only returns 0 children.
I need to initialize its children while creates it and hardly wait the control loaded. For example, whenever I set a Dependency Property Rows of the Custom Control to 4, the Grid which x:Name="G" will add&remove its RowDefinition to 4.
How can I solve this? Please help me.
Inside the CustomControl override OnApplyTemplate and use FrameworkElement.GetTemplateChild(String) to get a named element that is part of the template. OnApplyTemplate is invoked when the controls visual tree is created (template applied) and measured, but before the Loaded event.
public override void OnApplyTemplate()
{
var grid = GetTemplateChild("G") as Grid;
grid.RowDefinitions.Add(new RowDefinition());
}
use var g = (Grid)Control.Template.FindName("G",Control), here Control is the name of the the control you set the style to. it can be this. Cast what it returns to the the type of the the "G". Here (Grid). Then access all the children by saying g.Children[index] you can access the its properties like g.Row g.RowDefinations;

Having Trouble Styling and Editing AvalonDock Document Tab Panel

I'm trying to figure out how to make the VS2010 style for AvalonDock to function a little more like VS2010. The problem that I'm running into is that when there are more tabs than can fit in the header area there is no indication to the user that there are more tabs.
I thought that the tab headers were just clipped and not visible. I have a custom copy of the VS2010 style and went to the DocumentPane style:
<!--DocumentPane-->
<Style x:Key="{x:Type ad:DocumentPane}" TargetType="{x:Type ad:DocumentPane}"> ...
And found the tab headers (I think) as a "ad:DocumentTabPanel". I wrapped this in a ScrollViewer:
<ScrollViewer Style="{StaticResource ResourceKey=TabHeaderScrollViewer}" CanContentScroll="True">
<ad:DocumentTabPanel
x:Name="paneTabsPanel"
Panel.ZIndex ="1"
IsItemsHost="True"
TabItemStyle="{StaticResource CustomDocumentTabItemStyle}"/>
</ScrollViewer>
The scroll viewer is setup to have a custom style on it:
<Style x:Key="TabHeaderScrollViewer" TargetType="ScrollViewer">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ScrollViewer">
<Grid Background="{TemplateBinding Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<RepeatButton Command="ScrollBar.PageLeftCommand"></RepeatButton>
<ScrollContentPresenter Grid.Column="1"
x:Name="ScrollContentPresenter"
Cursor="{TemplateBinding Cursor}"
Margin="{TemplateBinding Padding}"
ContentTemplate="{TemplateBinding ContentTemplate}"/>
<RepeatButton Grid.Column="2" Command="ScrollBar.PageRightCommand"></RepeatButton>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The problem I am having is that even when I load up a ton of tabs the scrolling doesn't work. I don't think this is an issue with my styling. It appears that the tab headers aren't in the VisualTree or have a collapsed visibility. I've been going through the AvalonDock source for a while, but I can't see how the headers are hidden.
I've already had to subclass some of the AvalonDock classes because I needed additional properties on them.
Can someone either explain/help me come up with a solution to scroll the tabs?
Problem was solved very simply. I had to set the HorizontalScrollBarVisibility="Auto". I checked http://msdn.microsoft.com/en-us/library/system.windows.controls.scrollviewer.horizontalscrollbarvisibility.aspx to see what the default value is for this property, but didn't see one there or on the ScrollViewer page. I assume it defaults to "Hidden".
Anyhow, once set to "Auto" the repeat buttons are shown only when the tabs overflow.

Adding runtime label as content in checkbox wpf

I am dynamically creating the checkboxes at runtime and also applying the style at runtime. Designer has developed a checkbox like control that am applying at runtime. and he put a Label on that checkbox control to show the Text on the checkbox control as its content from the Database. But when i applying content of checkbox or label at runtime, it displays at the back of that checkbox control that is developed by the designer. How to make use of the Label control to show the content from the database on the checkbox control.
Kindly Suggest?
Thanks
It sounds to me like your designer forgot to include a <ContentPresenter/> in his checkbox template. If there is no ContentPresenter, the text you add as a comment will never be shown.
Here is an example of a custom CheckBox ControlTemplate that includes the required ContentPresenter:
<ControlTemplate TargetType="{x:Type CheckBox}">
<DockPanel>
<Border BorderThickness="1" BorderBrush="Black">
<Path x:Name="check" Width="10" Height="10"
Data=".... data for checkmark in checkbox ..." />
</Border>
<ContentPresenter/>
</DockPanel>
<ControlTemplate.Triggers>
<Trigger ... trigger for changing checkmark ... />
</ControlTemplate.Triggers>
</ControlTemplate>
You should to review your checkbox style. It is supposed to be that label(textbox) in style liyng under checkbox mark. Here is nearly right code for the chekcbox template:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Grid.Column="0">
<!--Place your mark here-->
</Border>
<Border Grid.Column="1">
<!--Place your label here-->
</Border>
</Grid>

WPF tab control spacing between headers

The default behavior of the WPF Tabcontrol is to place the Tab Headers adjacent to each other, without any empty space in between. What if I wanted to specify a gap between the headers? Do I have to define a control template for this? I'm relatively new to WFP and any help is appreciated.
Thanks
I believe you will need to define a custom control template for the TabItem, maybe even one for the TabControl. Here is an example of a TabItem that uses a spacer for some separation.
<Style
x:Key="SpacedTab"
TargetType="{x:Type TabItem}">
<Setter
Property="Template">
<Setter.Value>
<ControlTemplate
TargetType="{x:Type TabItem}">
<Border
x:Name="Spacer"
Width="Auto"
Height="Auto"
Padding="0 0 5 0"
Margin="0 0 0 0"
BorderBrush="Transparent"
BorderThickness="0">
<Border
x:Name="Border"
MinWidth="150"
Width="Auto"
Height="30"
Background="Gray"
BorderBrush="DarkGray"
BorderThickness="0,0,0,0"
CornerRadius="6,6,0,0"
Cursor="Hand"
VerticalAlignment="Bottom">
<ContentPresenter
x:Name="ContentSite"
TextElement.FontSize="10pt"
TextElement.FontFamily="Arial"
TextElement.Foreground="Black"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
Margin="8,3,8,3"
Width="Auto"
Height="Auto" />
</Border>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Hopefully that is a nudge in the right direction; you will still need to add that as a style resource and reference it from your TabControl -> TabItem.
It is easy to add space by doing it in the designer. Select the Tab you want to move, by starting with the rightmost tab. Then hold ctrl and use the right arrow key to move the tab to the right. Do the same with the rest of the tabs. Then you can manually adjust the margin in the xaml code.

Bind page title to a text block in a style

OK, I have defined a style for Navigation Window. I have successfully styled Navigation buttons and even added page breadcrumbs to the Navigation menu. What I want is to add Page title next to the breadcrumbs:
Style x:Key="{x:Type NavigationWindow}" TargetType="NavigationWindow">
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="NavigationWindow">
<DockPanel Background="{StaticResource WindowBackgroundBrush}">
...
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="16"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
....
<StackPanel Grid.Column="4" Orientation="Horizontal">
<TextBlock Foreground="Gray"
VerticalAlignment="Center"
Text="{Binding Path=Title,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Page}}}" />
</StackPanel>
</Grid>
</DockPanel>
...
</ControlTemplate>
</Setter.Value>
</Setter>
The binding doesn't work for the last TextBlock. (However it works just fine if not used within a style, but in regular XAML page code-behind) I have no idea why. Help? How to make it display the current page title? Thanks.
The problem is that within the ControlTemplate, there is no ancestor of type Page. The control you apply the template to may have an ancestor of type Page, but the ControlTemplate itself doesn't know about that. It only knows about ancestors in its own logical tree.
To help mitigate this issue, the WPF designers added the TemplateBinding markup extension, which allows you to apply the value of a property on the templated control to a property in the control template.
So, on the NavigationWindow, you should create a property that exposes the Title of the Page. Then you can use the following mark-up to bind to it:
Text="{TemplateBinding TitleProperty}"

Resources