I have ComboBox item style as follows (simplified):
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="35"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" />
<Path Grid.Column="1" Style={StaticResource StarStyle}/>
</Grid>
The result is as expected. An item in my list looks as follows:
alt text http://robbertdam.nl/share/p1.png
Howver, when I select that item. It looks like this:
alt text http://robbertdam.nl/share/p2.png
I want to have the stars right aligned. What am I missing?
I forgot to mention that I've defined this Style
<Style x:Key="ComboItemsStyle" TargetType="{x:Type ComboBoxItem}">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
Assigning this style to my ComboBox solves it:
<Style x:Key="ComboStyle" TargetType="{x:Type ComboBox}">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
Does the "Path" object have an "Align" property? That is, can you force it to align right with this XAML?
<Path Grid.Column="1" Align="Right" Style={StaticResource StarStyle}/>
Edit
No, it doesn't. In that case, I'd suggest embedding the path into a container that can align it. Perhaps:
<DockPanel Grid.Column="1">
<Path DockPanel.Dock="Right" Style={StaticResource StarStyle}/>
</DockPanel>
Related
I am adding a WPF DatePicker control to my form and it works fine. But I don't want the user to be able to type in a type in the 'Select a date' textbox. I want that to be readonly and when they click the textbox it just opens the calendar.
I wasn't sure if there was an option for this in the properties? I couldn't find anything...
<DatePicker HorizontalAlignment="Left" VerticalAlignment="Top">
<DatePicker.Resources>
<Style TargetType="DatePickerTextBox">
<Setter Property="IsReadOnly" Value="True"/>
<Setter Property="Text" Value=" "/>
<Setter Property="Focusable" Value="False"/>
<Setter Property="IsEnabled" Value="False" />
<Setter Property="IsHitTestVisible" Value="False"/>
</Style>
</DatePicker.Resources>
</DatePicker>
In future you can use the WPF visualizer to see which child controls a top-level control is using (in this case DatePickerTextBox) and then apply a style and/or template to that type in the resources section like I've done here.
The answer of Mark Feldman is partially right, he had not answer to how clicking on the textbox gonna open the calendare popup!
You should hook the template of the DatePicker and enlarge the size of the button so it will overlap the textbox: then you are done, when you click on the textbox it's the button that get the event see below a part of the modified template of DatePicker:
<DatePickerTextBox Grid.Row="0" Grid.Column="0" x:Name="PART_TextBox" Focusable="{TemplateBinding Focusable}" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch"/>
<Button Grid.Row="0" Grid.Column="0" x:Name="PART_Button" Foreground="{TemplateBinding Foreground}" Focusable="False" >
<Button.Template>
<ControlTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Border Background="Transparent"/>
<Button Grid.Column="1" HorizontalAlignment="Left" Foreground="{TemplateBinding Foreground}" Template="{StaticResource DropDownButtonTemplate}" VerticalAlignment="Top" Width="20" Margin="3,0,3,0" />
</Grid>
</ControlTemplate>
</Button.Template>
</Button>
Dont forget to add the style of DatePickerTextBox described in the answer of Mark Feldman
You can open calendar this way :
<DatePicker Name="datePicker" Focusable="False">
<DatePicker.Resources>
<Style TargetType="DatePickerTextBox">
<EventSetter Event="MouseLeftButtonUp" Handler="OnMouseLeftButtonUp" />
</Style>
</DatePicker.Resources>
</DatePicker>
private void OnMouseLeftButtonUp(object sender, RoutedEventArgs e)
{
datePicker.IsDropDownOpen = true;
}
I'm new to the WPF stuff around and I tried restyling a TabItem myself.
As you people can see the tabs are filling the window's whole width. Unlike my original purpose which I actually wanted to make the tabs width is based on the text inside of it. Like the original style, only redesigned.
My style in code:
<Style x:Key="ZoidTab" TargetType="{x:Type TabItem}" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate x:Name="ZoidTemplate" TargetType="{x:Type TabItem}">
<Border Width="Auto" Height="Auto">
<Grid x:Name="grid">
<Polygon
Fill="Turquoise"
Points="0,1 0.05,0 0.95,0 1,1"
Stretch="Fill"
Margin="0,0,0,0"
/>
<ContentPresenter x:Name="tabContent" HorizontalAlignment="Center" ContentSource="Header" VerticalAlignment="Center" TextElement.Foreground="#FFFFFFFF"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="FontSize" Value="12pt"/>
</Style>
I'd like to know what is it that I must fix to get the width right... Thank you.
The problem is that your Grid doesn't have a ColumnDefinitions section to limit the size of the one and only column. Modify it to look like this:
<Grid x:Name="grid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
...
I'm trying to simplify some code and improve my maintainability.
I was initially seeking a way to have a text box aligned to the left, that can shrink and expand to a maximum value without centering inside a grid cell after reaching the maximum value.
So I started out writing some code like this...
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
</Grid.ColumnDefinitions>
<TextBox Text="Some text"
VerticalAlignment="Center"
HorizontalAlignment="Stretch"
Margin="10"
MaxWidth="150" />
</Grid>
(Code Listing 1)
And that yields something looking like this...
(Figure 1)
As you can see, this centers the TextBox with it's max width, but it is aligned in the center of the grid cell.
So then I though maybe if i changed the horizontal alignment of the text box like so...
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
</Grid.ColumnDefinitions>
<TextBox Text="Some text"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="10"
MaxWidth="100" />
</Grid>
(Code Listing 2)
But unfortunately, that only yields something looking like this...
(Figure 2)
Again, this isn't right because, despite all the empty space on the right, the text box is not expanding to its max width of 100 like I want.
Eventually, I found that if put the TextBox inside a nested grid, you will achieve the desired effect.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
</Grid.ColumnDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"
MaxWidth="120" />
<ColumnDefinition Width="0*" />
</Grid.ColumnDefinitions>
<TextBox Text="Some text"
VerticalAlignment="Center"
HorizontalAlignment="Stretch"
Margin="10"
MaxWidth="100" />
</Grid>
</Grid>
(Code Listing 3)
Which yields this...
(Figure 3)
As you can see, the nested grid fills the entire 200 wide space, but the text box fills the left 100, and leaves the empty space on the right. (If this window is re-sizable it will shrink and expand appropriately)
I would like to apply the methods of Code Listing 3 to a style or control template, so I can blanket apply it to TextBoxes where this situation is applicable.
In a perfect scenario, I would do something like...
<TextBox Text="Some text"
VerticalAlignment="Center"
HorizontalAlignment="Stretch"
Margin="10"
MaxWidth="100"
Style="{StaticResource ExpandingTextBox}" />
(Code Listing 4)
And achieve the same results as Figure 3.
I tried the following...
<Style TargetType="{x:Type TextBox}"
x:Key="ExpandingTextBox">
<Setter Property="OverridesDefaultStyle"
Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"
MaxWidth="170" />
<ColumnDefinition Width="0*" />
</Grid.ColumnDefinitions>
<ContentPresenter/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
(Code Listing 5)
But that just causes the text box to disappear from my form all together. I'm not very good at writing templates like this, so I'm kind of at a loss.
Also, one thing I just realized is that the width of the nested column = MaxWidth + 2 x Margin. I wouldn't mind setting the column width explicitly in the TextBox declaration, but if it could be automatic, that would be awesome.
You need a TextBox instead of ContentPresenter inside your Template. You replaced default template for TextBox with one that no longer has area for text input.
Try like this:
<Style TargetType="{x:Type TextBox}" x:Key="ExpandingTextBox">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"
MaxWidth="170" />
<ColumnDefinition Width="0*" />
</Grid.ColumnDefinitions>
<TextBox Text="{TemplateBinding Text}"
VerticalAlignment="Center"
HorizontalAlignment="Stretch"
Margin="10"
MaxWidth="100"
/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
This should work but imo, is a bit wierd..
Thanks to jure for getting me started. As always, it turns out that the solution is a bit more convoluted than it originally lets on.
Let's examine what I did.
Using the ideas presented in the previous post, and after a bit of finagling, I came up with the following code.
<Style TargetType="{x:Type TextBox}"
x:Key="ExpandingTextBox">
<Setter Property="OverridesDefaultStyle"
Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*">
<ColumnDefinition.MaxWidth>
<Binding Path="MaxWidth"
RelativeSource="{RelativeSource TemplatedParent}">
</Binding>
</ColumnDefinition.MaxWidth>
</ColumnDefinition>
<ColumnDefinition Width="0*" />
</Grid.ColumnDefinitions>
<TextBox Text="{TemplateBinding Text}">
<TextBox.MaxWidth>
<Binding Path="MaxWidth"
RelativeSource="{RelativeSource TemplatedParent}" />
</TextBox.MaxWidth>
</TextBox>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
(Code Listing 6)
And of course applied it in the XAML markup for my page like this...
<TextBox Grid.Column="1"
Grid.Row="3"
Text="{Binding Path=Username}"
Style="{StaticResource ExpandingTextBox}"
Margin="10"
MaxWidth="200" />
(Code Listing 7)
That gives a result like this...
(Figure 4)
After looking at that image, and thinking for a while, it donned on me that the problem was that even though I was applying the max width inside the style correctly, the max width property was still being applied to the root of the control in XAML.
Essentially it was squeezing it down to the max width on the page, and then after that was done, it applied the max width pursuant to the styling!
So simple, but so elusive!
Therefore, I modified the style to use the Tag property to apply to the styled max width elements, since the Tag property doesn't do anything at the root.
<Style TargetType="{x:Type TextBox}"
x:Key="ExpandingTextBoxMaxWidthInTag">
<Setter Property="OverridesDefaultStyle"
Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*">
<ColumnDefinition.MaxWidth>
<Binding Path="Tag"
RelativeSource="{RelativeSource TemplatedParent}">
</Binding>
</ColumnDefinition.MaxWidth>
</ColumnDefinition>
<ColumnDefinition Width="0*" />
</Grid.ColumnDefinitions>
<TextBox Text="{TemplateBinding Text}">
<TextBox.MaxWidth>
<Binding Path="Tag"
RelativeSource="{RelativeSource TemplatedParent}" />
</TextBox.MaxWidth>
</TextBox>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
(Code Listing 8)
Which is applied in XAML like this...
<TextBox Grid.Column="1"
Grid.Row="3"
Text="{Binding Path=Username}"
Style="{StaticResource ExpandingTextBoxMaxWidthInTag}"
Margin="10"
Tag="200" />
And finally gives the desired results like this...
(Figure 5)
(Figure 6)
So, the real trick was realizing that I didn't necessarily want to limit the max width of the entire templated control, but instead just wanted to limit the width of the TextBox internal to the control!
Once I figured that out, it only made sense to use the Tag property which wasn't doing anything to the control at the root level!
I hope this helps anyone else who might have this problem!
How can I set Visibility="Visible" for the Button inside the Control Template when the IsSendBtnVisible property in the code-behind is true?
Here's my WPF page:
<Page
x:Class="CardViewPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="CardViewPage">
<Grid Name="content" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<DocumentViewer Margin="0" Grid.Row="0" Name="documentViewer" />
</Grid>
</Page>
Here's my Custom Template for the document viewer on this page:
<Style TargetType="{x:Type DocumentViewer}">
...
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DocumentViewer}">
...
<Button
Click="btnSendToServer_Click"
Width="25"
Height="25"
Visibility="Collapsed" />
...
</ControlTemplate>
</Setter>
...
</Style>
U need to declare DependancyProperty for ur DocumentViewer and use TemplateBinding in xaml ControlTemplate (UrProperty for example)
<ControlTemplate TargetType="{x:Type DocumentViewer}">
...
<Button Click="btnSendToServer_Click"
Width="25"
Height="25"
Visibility="{TemplateBinding UrProperty}"
/>
...
</ControlTemplate>
I suggest you to use data triggers to achieve this...
<Button
Click="btnSendToServer_Click"
Width="25"
Height="25">
<Button.Style>
<Style>
<Setter Property="Button.Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsSendBtnVisible}" Value="True">
<Setter Property="Button.Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
Make sure to set visibility to collapsed in the style but not in the button properties..
Note: Binding for data trigger may change depending on your data context
Dima Martovoi,bathineni - thanks for replies.
Dima Martovoi, i think inherit from DocumentViewer is to hard for this small problem.
I tried to use variant with DataTrigger from bathineni's solution, but it's not works. Don't know, why.
Problem was solved using next binding:
<Button
Visibility="{Binding RelativeSource={RelativeSource AncestorType=Page},Path=SendToServerVisiblity}">
</Button>
where
public Visibility SendToServerVisiblity
{
get
{
if (IsOnlineMode)
return Visibility.Visible;
return Visibility.Collapsed;
}
}
in page code-behind
Any advice how to fault find to work out why the Grid.Resources styles in this XAML is not making any difference it seems to the end result?
Note I'm using Charting from the WPFToolkit so to adjust how a chart looks it seems one has to apply the style areas (suggested by someone on the forum).
So my question is generically, noting I'm trying to adjust the look of a 3rd party graph, how can I debug/fault-find to understand what's going wrong? Is there a debugging trick? For example when I increased the BorderThickness to 30 I couldn't see a difference. What I'm really after is the equivalent of FireBug for HTML/CSS, which lets you understand/view what CSS is being applied to what elements.
EDIT: So I really (I think) want to be able to walk the object tree of the graph, and referring back to the template changes put in the Grid.Resources area, see why they didn't occur.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:chartingToolkit="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit" mc:Ignorable="d" x:Name="Splash" x:Class="MyInternetUsage.SplashWindow"
Title="SplashWindow" Height="421" Width="570">
<DockPanel>
<StackPanel VerticalAlignment="Top" DockPanel.Dock="Top" Orientation="Horizontal">
<Button Content="Configure" HorizontalAlignment="Left" Margin="0" Width="78" VerticalAlignment="Center" Name="ConfigureButton" Click="ConfigureButton_Click" />
<Button Content="Start" Name="StartButton" Width="78" Click="StartButton_Click" />
<Button Content="Stop" Name="StopButton" Width="78" Click="StopButton_Click" />
</StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Content="Summary" Grid.Column="0"/>
<GridSplitter HorizontalAlignment="Right"
VerticalAlignment="Stretch" Grid.Column="1" ResizeBehavior="PreviousAndNext"
Width="5" Background="#FFBCBCBC"/>
<Grid Grid.Column="2">
<Grid.Resources>
<Style x:Key="GooglePolylineStyle" TargetType="Polyline">
<Setter Property="StrokeThickness" Value="30"/>
</Style>
<Style x:Key="GoogleLineDataPointStyle" TargetType="chartingToolkit:LineDataPoint">
<Setter Property="Background" Value="#0077CC" />
<Setter Property="BorderBrush" Value="White"/>
<Setter Property="BorderThickness" Value="30"/>
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="chartingToolkit:LineDataPoint">
<Grid x:Name="Root" Opacity="1">
<ToolTipService.ToolTip>
<StackPanel Margin="2,2,2,2">
<ContentControl Content="{TemplateBinding IndependentValue}"
ContentStringFormat="{}{0:MMMM d, yyyy}"/>
<ContentControl Content="{TemplateBinding DependentValue}"
ContentStringFormat="Visits {0:###,###,###}"/>
</StackPanel>
</ToolTipService.ToolTip>
<Ellipse StrokeThickness="{TemplateBinding BorderThickness}"
Stroke="{TemplateBinding BorderBrush}"
Fill="{TemplateBinding Background}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<Label Content="Real Time Graph" VerticalAlignment="Top" Grid.Row="0" />
<chartingToolkit:Chart Grid.Row="1"
Name="RTGraph"
BorderThickness="0" >
</chartingToolkit:Chart>
</Grid>
</Grid>
</DockPanel>
</Window>
As SeeSharp says, Snoop allows you to view the object tree at runtime (and change values and see results etc). However, I think your problem here might be that you're not explicitly applying the style on the <chartingToolkit:Chart /> object.
Try one of the following to see if it makes a difference:
Apply style on object:
<chartingToolkit:Chart
...
Style="{DynamicResource GoogleLineDataPointStyle}"
...
>
Or remove the key from the style so that it only has a TargetType attribute (should make it the default style for all objects of that type:
<Style TargetType="chartingToolkit:LineDataPoint">
...
</Style>
Since you've given the styles an x:Key. you need to explicitly set the style property of your items to use that style as a resource.
Have you tried removing the x:Key properties from your style, and moving your style declaration from the grid and into the chart?
See output window in VS. All binding errors logged in this window. Also, tool Snoop alow to see bindings with errors.
If this is a WPF application, i would like to suggest one silly thing. Excuse me for that. Please copy and paste the same code into a silverlight application and then inspect the element using Firebug.
Also, in your code snippet, i think you need to give :
TargetType="{x:Type Polyline}"
TargetType="{x:Type chartingToolkit:LineDataPoint}"
If you want these styles to be applied on the target type automatically, then remove the x:Key.
Also, you can find a list of useful WPF utilities # http://www.simple-talk.com/dotnet/.net-tools/essential-tools-for-the-wpf-novice/