Radiobuttons and Silverlight - silverlight

I have radiobutton in Silverlight 3 with FontSize=20.
Within the control the radio dialog image forced to the top alignment.
Relative to the text/content the image appears too high. This is not obvious with smaller text sizes however with the large text size the vertical alignment between the text/content and the dialog image looks ugly.
Any ideas on how to vertical-align = middle both the text and the dialog image?
ty

The image inside the RadioButton consists of several Ellipse elements grouped into a Grid element. If you take a look at the RadioButton template (use Expression Blend to edit a copy of the existing template) you will see that the Grid elements VerticalAlignment is set to Top.
<Grid HorizontalAlignment="Left" VerticalAlignment="Top">
<Ellipse x:Name="Background" Fill="#FFFFFFFF"
Stroke="{TemplateBinding BorderBrush}"
StrokeThickness="{TemplateBinding BorderThickness}"
Height="14" Margin="1" Width="14"/>
...
The ContentPresenters (where your text is displayed) VerticalAlignment is set to the value you set in the VerticalContentAlignment property.
<ContentPresenter x:Name="contentPresenter"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Grid.Column="1" Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"/>
To fix your problem you need to set the VerticalAlignment of the Grid element to Middle or use TemplateBinding to set it to the VerticalContentAlignment value.
<Grid HorizontalAlignment="Left"
VerticalAlignment="Middle">
OR
<Grid HorizontalAlignment="Left"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}">

It appears the best way is to use something like Padding="5,-7,0,0"

Related

Multiselect WPF combo box

I have a WPF combo box which ItemsSource is ObservableCollection<User>, where User has string Name and bool IsChecked.
Also I have
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding IsChecked}" Width="20" />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
, which nicely shows check boxes before each name and allows me to check/uncheck users.
What I need is to make combo box selected item to show not the selected user but all checked usernames separated by comma, ideally (if resultant string is too long) with ellipsis in the middle, i. e. "Alice, Bart...mew, John".
Possible?
A little bit tricky to implement, but certainly can be done.
First of all you'll want to replace the drop-down bar/button with a TextBlock, so you'll need to modify the control's template. Place the edit cursor anywhere inside the parent ComboBox declaration so that the control appears in the Properties panel at the bottom right. In properties, find Miscellaneous -> Template at the bottom, then click on the little down-arrow to the right and select "Convert to new resource". This will template out the control so that you can start editing it.
Next, find the ToggleButton's ContentPresenter inside the ControlTemplate. You'll want to change it's Content binding to point to a property in your view models which I'll call Names:
<!--<ContentPresenter x:Name="contentPresenter" ContentStringFormat="{TemplateBinding SelectionBoxItemStringFormat}" ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" Content="{TemplateBinding SelectionBoxItem}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" IsHitTestVisible="false" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>-->
<ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" Content="{Binding Names}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" IsHitTestVisible="false" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
The next change is to also add a binding to your CheckBox Command property called "NamesChangedCommand" which will be called whenever the user changes the state of a CheckBox:
<CheckBox IsChecked="{Binding IsChecked}" Width="20" Command="{Binding RelativeSource={RelativeSource AncestorType=ComboBox}, Path=DataContext.NamesChangedCommand}" />
Then back in your view model, all you have to do is implement this command and have it generate the new name list. Here's how you'd do that in MVVM Toolkit:
[RelayCommand]
public void NamesChanged()
{
this.Names = String.Join(", ",
this.Items
.Where(item => item.IsChecked)
.Select(item => item.Name));
}
[ObservableProperty]
private string names = "";
Result:
I was going to suggest the xceed checkcombobox
https://github.com/xceedsoftware/wpftoolkit/wiki/CheckComboBox
But I notice it's not free for commercial use any more. You could build something of your own based on their code though.
https://github.com/xceedsoftware/wpftoolkit/blob/master/ExtendedWPFToolkitSolution/Src/Xceed.Wpf.Toolkit/CheckComboBox/Implementation/CheckComboBox.cs
The xaml will be in that repo as well.

From where a control(Say, a Button) gets its width in a Layout Panel(Stackpanel) in case it is not explicitly set?

I am currently learning WPF and during this I came across HorizontalAlignment/VerticalAlignment Properties that can be set for a control and determines that where a control will be placed in a Layout control when there is extra space is available.
Now, I was looking into following code block:
<StackPanel>
<Label HorizontalAlignment="Center">A Button Stack</Label>
<Button HorizontalAlignment="Left">Button 1</Button>
<Button HorizontalAlignment="Right">Button 2</Button>
<Button>Button 3</Button>
<Button>Button 4</Button>
</StackPanel>
Now, when I place this code in a window and execute, It is displayed like this:
Horizontal/VerticalAlignment
My Query is: From where does the width of Button1 and Button2 is determined since I have not set and width property for those controls?
Default behavior of StackPanel is to stack the controls vertically and HorizondalAlignment of the items will be Stretch and vice versa if you switch the Orientation.
On setting the HorizontalAlignment to Left or Right leads to make the control to have their Width as designed.
To answer your question on Width of the Button, the default template of the Button is designed in such a way as
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<ContentPresenter x:Name="contentPresenter" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
Border has the default capability to adjust its Width based on the Content it holds.
In your case, the Content is a text "Button 1" which occupies some width and that will be the width of the Button

WPF CheckBox is not squared

I have a strange bug here. CheckBox controls has always been squared. Now I've noticed that it's not. It's one pixel wider than tall. After experimenting a bit with empty WPF applications, I've discovered that it depends on the UseLayoutRounding setting. If it's set to false, the CheckBox is never a square. If it's set to true, it depends on the actual layout values and how they are rounded, or snapped to pixels.
Just create an empty WPF application targeting .NET Framework 4.5.2, 4.6 or 4.6.1 (I've tested these) and run it on Windows 10. Here's the minimal XAML to reproduce. The third state shows another filled "square" box that makes it easier to recognise the form without measuring pixels.
<Window
x:Class="CheckBoxTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" UseLayoutRounding="False">
<Grid>
<CheckBox HorizontalAlignment="Center" VerticalAlignment="Center" IsThreeState="True" IsChecked="{x:Null}"/>
</Grid>
</Window>
Then drag the window's width and watch the CheckBox as it toggles between square and one pixel wider. In another of my applications it's always one pixel wider and never has a squared form.
Is that a bug in WPF? Does it only happen on Windows 10?
PS: Better not use a high DPI monitor for this, it may be harder to see there.
Its a bug in the default style of the checkbox. For some reason they decided to not use layout rounding on the grid in the checkbox control template.
<Border x:Name="checkBoxBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="1" VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<Grid x:Name="markGrid" UseLayoutRounding="True">
<Path x:Name="optionMark" Data="F1 M 9.97498,1.22334L 4.6983,9.09834L 4.52164,9.09834L 0,5.19331L 1.27664,3.52165L 4.255,6.08833L 8.33331,1.52588e-005L 9.97498,1.22334 Z " Fill="{StaticResource OptionMark.Static.Glyph}" Margin="1" Opacity="0" Stretch="None"/>
<Rectangle x:Name="indeterminateMark" Fill="{StaticResource OptionMark.Static.Glyph}" Margin="2" Opacity="0"/>
</Grid>
</Border>
Maybe because even if you modify the template like this, it still inchworms when you resize it in the designer, but not when you run it.

XAML Property Element Not Found in Parent, what does it mean?

I have been drilling through XAML and trying to puzzle together how it actually works.
I have got the following XAML from one of the sample code I downloaded, an earlier question has explained away a large part of my confusion, however... I am still trying to make sense why the following element has a child element that references another type altogether.
<Border HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<VisualStateManager.VisualStateGroups>
<!-- Snipped code irrelevant - just various storyboards-->
</VisualStateManager.VisualStateGroups>
<Grid x:Name="InnerGrid"
Opacity="1"
Margin="0,5,0,5"
Background="{StaticResource TransparentColor}">
<ContentPresenter x:Name="ContentPresenter"
Foreground="{StaticResource TransparentColor}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
</Border>
Looking at the XAML syntax documentation, the VisualStateManager is a PropertyElement, however I am confused because VisualStateGroups do not appear to be a property of Border. I believe the example is correct however, I need someone to explain to me, how is an element that's not a "proper" Child element (as that's what Grid is), be a legit part of the parent element?
VisualStateManager.VisualStateGroups is attached property. Read the following topic, it may help you: http://msdn.microsoft.com/en-us/library/ms749011.aspx

How to make a plain text-only Silverlight button?

I simply want a button with no background or anything other than plain text. I have done the following and the button does not show up at all:
<UserControl.Resources>
<ControlTemplate x:Key="linkButtons" TargetType="Button">
<TextBlock Foreground="White" FontSize="28" FontFamily="Verdana" Padding="10"></TextBlock>
</ControlTemplate>
</UserControl.Resources>
<Button Template="{StaticResource linkButtons}" Content="Hello World!"/>
This is because the TextBlock inside the Control template does not have a template binding. Make an attribute like this:
<TextBlock Foreground="White" FontSize="28" FontFamily="Verdana" Padding="10" Text="{TemplateBinding Content}" />
Not sure if thats the correct syntax, but thats the concept.
The problem is that a button is designed to have content, not text - it's a kind of ContentControl. So, to display the content, your template should have this in it:
<ContentPresenter x:Name="contentPresenter"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"/>
OR, you could make a custom control based on button, add a Text property to it, use your current TextBlock control in the template (but with Text="{Binding Text}") and leave the ContentPresenter out of your template. Making a custom control is a little trickier than just making a template for an existing one, but it's really the best way to get exactly what you're going for.

Resources