WPF controls custom design - c#

I need to create some controls that look like the following pictures and I have no idea which control to use or how to make it look like I want:
1) An horizontal bar, such that I could change its length dynamically in code.
Iv'e tried using the "Progress bar" control for it, but I can't get rid of the green glow effect, nor the white border:
2) A slider that looks like:
Notice that I have all images of the slider, separately. (The background with the "plus" and "minus" buttons, The thumb etc..)
3) Dynamically changed amount of blades, like (when I have the image for the blade):

You will have to create a custom template for the slider, the progress bar.
On MSDN, there are the style and template for the standard WPF controls.
Then, for your "blades" control, I think you will have to create a new custom control, maybe based on RangeBase.
For the progress bar you can begin with:
<ProgressBar VerticalAlignment="Top" Value="60" Maximum="100">
<ProgressBar.Template>
<ControlTemplate TargetType="{x:Type ProgressBar}" >
<Grid Height="20">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<Grid x:Name="PART_Track" ClipToBounds="True">
<Rectangle x:Name="PART_Indicator" Margin="-7,0,0,0" HorizontalAlignment="Left" Fill="Green" RadiusX="7" RadiusY="7" Height="14"/>
</Grid>
<TextBlock Grid.Column="1" Text="{Binding Value, RelativeSource={RelativeSource TemplatedParent}, StringFormat={}{0} %}" Foreground="Black" VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
</ProgressBar.Template>
</ProgressBar>

Related

In my WPF control, can I hide the validation control based on the size of the adorned element's row?

I have a user control with many sub controls within a grid. Since there are many controls per row, I'm controlling the visibility of the controls by setting the row height of their containing row to 0 (to hide them).
I'm using a validation template on some of these controls and displaying an icon next to the control using AdornedElementPlaceholder.
Since I'm not actually setting the visibility property of the adorned control, but instead hiding the row, the validation icon is not collapsed with the rest of the control.
Here's an abridged version of my XAML code:
<UserControl
<UserControl.Resources>
<ControlTemplate x:Key="ValidationTemplate" TargetType="Control">
<DockPanel>
<Grid
Width="16"
Height="16"
Margin="10,0,0,0"
VerticalAlignment="Center"
DockPanel.Dock="Right">
<Image Source="{x:Static icons:Icons.ValidationIcon}" ToolTip="{Binding Path=ErrorContent}" />
</Grid>
<AdornedElementPlaceholder />
</DockPanel>
</ControlTemplate>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="32"/>
<RowDefinition Height="{Binding Path=ScheduleType, Mode=OneWay, Converter={StaticResource ScheduleTypesToGridRowHeightConverter}, ConverterParameter={x:Static local:ScheduleTypes.Other}}"/>
<RowDefinition Height="{Binding Path=ScheduleType, Mode=OneWay, Converter={StaticResource ScheduleTypesToGridRowHeightConverter}, ConverterParameter={x:Static local:ScheduleTypes.Fixed}}"/>
<RowDefinition Height="{Binding Path=ScheduleType, Mode=OneWay, Converter={StaticResource ScheduleTypesToGridRowHeightConverter}, ConverterParameter={x:Static local:ScheduleTypes.Weekly}}"/>
<RowDefinition Height="{Binding Path=ScheduleType, Mode=OneWay, Converter={StaticResource ScheduleTypesToGridRowHeightConverter}, ConverterParameter={x:Static local:ScheduleTypes.FreeText}}"/>
</Grid.RowDefinitions>
<controls:DateInputBox
Grid.Column="2"
Grid.Row="5"
Height="28"
HorizontalAlignment="Left"
Watermark=""
Width="110"
Text="{Binding StartDateText, ValidatesOnDataErrors=True, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"
Validation.ErrorTemplate="{StaticResource ValidationTemplate}"
VerticalAlignment="Center"
ParseComplexDates="True"/>
</Grid>
</UserControl>
From what I understand from a little research is that the validation icon is being displayed in the adorner layer, so doesn't collapse with the rest of the controls.
I'm now thinking that the "row height visibility pattern" was maybe not the best approach ;-) Is there a way I can get this to work without having to completely change my design? I do have a workaround using my view model but I'd like to explore other options first.
If you really whant to stick with the design, you could remove and add the adornents depending of what you whant to display. However, this would be pretty messy and defeat the point of sticking with the current desing for simplicity in the first place.
The concept of hiding elements by setting their parent element size to zero is indeed not the best option. Partly because of the exact issue you mentioned. (The adornents visibility is dependent on its owners visibility. And the owner elements visibility is visible, there is just no space to render it.)
A better option would be to only show whatever is to be shown. An easy way to accomplish this would be to encapsulate all the elements you whant to hide/show together inside one element or user control and then hide or show only that parent element or user control.
This could for instance look like this:
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVis" />
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="32"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Border Grid.Row="1" Visibility="{Binding FixedIsVisible, Converter={StaticResource BoolToVis}">
<!-- fixed shedule content here -->
</Border>
<Border Grid.Row="1" Visibility="{Binding WeeklyIsVisible, Converter={StaticResource BoolToVis}">
<!-- weekly shedule content here -->
</Border>
<Border Grid.Row="1" Visibility="{Binding FretextIsVisible, Converter={StaticResource BoolToVis}">
<!-- free text shedule content here -->
</Border>
</Grid>
By using some other converter you also yould directly bind you ScheduleType so you dont need to touch your view model.
A maybe even better option would be to make it so that only the elements you need at a time exist inside the view. This could be acomplished by defining different user controls and then have your grid line contain only the desired control at a time. (I might add an example for this later when i have time to do so.)

How to make a rounded Border and Background colour exactly fit the text extents in a TextBlock?

I've got the following XAML:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="140"/>
<ColumnDefinition Width="60"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Level}"/>
</Grid>
Level is basically a log level (Verbose, Information, Warning, Error).
First I would like to add a background colour but only to the text itself.
If I do <TextBlock Text="{Binding Level}" Background="Yellow"/> then I end up with something like this:
Verbose
I can workaround that by doing the following:
<TextBlock>
<Run Text="{Binding Level}" Background="Yellow"/>
</TextBlock>
And now I correctly end up with:
Verbose
But now I would like to round the corners of just the text itself, and that ... I can't find a way to do and would appreciate some help with.
I've tried adding a Border to the TextBlock but that creates a border around the whole TextBlock, not just the text inside it.
If you set an HorizontalAlignment and VerticalAlignment on a FrameworkElement like a Border or TextBlock, it will prevent it from stretching to its parent size (which is the default behavior).
You can write the following XAML:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="140"/>
<ColumnDefinition Width="60"/>
</Grid.ColumnDefinitions>
<Border Background="Yellow" CornerRadius="5" HorizontalAlignment="Left" VerticalAlignment="Top">
<TextBlock Text="Hello"/>
</Border>
</Grid>
And the Border only takes the space needed to fit its child TextBlock.

How to change telerik WPF RadGridView column filtering view template

We are using telerik controls in our project. I want to change telerik Radgrid view's (For WPF) filtering view.
As of now it looks like this as shown below:
And I want to change the text being show to actual color, so that it looks more realistic for the user to filter. Something like this:
How to get hold of the template of filtering view and inject the color rectangle there.
How to get hold of the template of filtering view and inject the color rectangle there.
The ControlTemplate can be found in Telerik.Windows.Controls.GridView.xaml:
<ControlTemplate x:Key="FilteringControlTemplate" TargetType="grid:FilteringControl">
...
I customized the ItemTemplate (for the Office2013 theme) to achieve the following, which should give you an indication of what needs to be done. You could also have a look at the CustomFilterControl example.
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<CheckBox
Content=""
FontSize="13"
Grid.Column="0"
IsChecked="{Binding IsActive, Mode=TwoWay}"
VerticalAlignment="Center"/>
<Rectangle
Fill="{Binding ConvertedValue, Converter={StaticResource DistinctValueConverter}}"
Grid.Column="1"
Height="16"
Width="30" />
</Grid>
</DataTemplate>

Force Size on a Viewbox's Children

So I have a rather interesting question. I have a viewbox that has a few elements in it (a custom user control for an image, a canvas, a label, and a textbox). What I want is to try and have all elements scale with the viewbox, but I want the label and the textbox to have a "Max Size." I have tried using a max width and height on these controls but they seem to ignore it. If someone could take a look at my code below an slap me for what I am doing wrong that would be appreciated.
<Viewbox Name="myViewBox" Stretch="Uniform">
<!--Grid used to track mouse movements in this element for other reasons -->
<Grid Name="grdViewboxGrid" MouseMove="trackMouse">
<Canvas Name="cvsViewboxCanvas" MinWidth="270" MinHeight="270"
VerticalAlignment="Top" HorizontalAlignment="Center"
Panel.ZIndex="1" Background="Black"
MouseUp="Canvas_MouseUp"
MouseMove="Canvas_MouseMove">
<Grid>
<!--Would rather not post here for Intellectual Property reasons-->
<!-- Extension of the image control -->
<CustomImageUserControl />
<Grid>
<Grid Width="{Binding LabelWidthPercentage}"
MaxWidth="50"
Height="{Binding LabelHeightPercentage"
MaxHeight="26"
SnapsToDevicePixels="True" VerticalAlignment="Top"
HorizontalAlignment="Left" Margin="5" IsHitTestVisible="False">
<Label Name="lblViewboxLabel" HorizontalAlignment="Left"
Padding="5,5,5,0" Margin="0,5,0,0"
Style="{x:Null}"
Content="{Binding lblContent}" />
</Grid>
<Grid>
<Grid Width="{Binding TextBoxWidthPercentage}"
MaxWidth="156"
Height="{Binding TextBoxHeightPercentage}"
MaxHeight="45"
SnapsToDevicePixels="True" Vertical="Top"
HorizontalAlignment="Right" Margin="5" IsHitTestVisible="False">
<Border Style="{DynamicResource CustomBorder}" />
<Grid>
<Textbox Name="txtViewboxTextBox" Text="{Binding txtViewbox}" />
</Grid>
</Grid>
</Grid>
</Grid>
</Grid>
</Canvas>
</Grid>
</Viewbox>
If I am not including something that is needed please let me know and I will update my question. Any help would be greatly appreciated this is now day 4 on this issue sadly :-(
I am not sure why you need so many overlapping Grids, but I hope that I can answer your question nevertheless:
In order to have the label left of the text box and to assign a maximum width to each of these two controls, use a Grid with two columns and set the MaxWidth property for each column. Then, assign the label to the left column (the one with index 0) and assign the text box to the right column (index 1). The corresponding code fragment looks like this:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition MaxWidth="30"/>
<ColumnDefinition MaxWidth="156" MinWidth="30"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" x:Name="lblViewboxLabel" HorizontalAlignment="Left" Foreground="Yellow"
Padding="5,5,5,0" Margin="0,5,0,0"
Style="{x:Null}"
Content="{Binding lblContent}" />
<TextBox Grid.Column="1" x:Name="txtViewboxTextBox" Text="{Binding txtViewbox}" Background="Orange"/>
</Grid>
I also have assigned a MinWidth to the right column; this is necessary to make sure that the text box does not completely disappear if it contains no text.

WPF Create a slide out panel

I don't know how this works technically but my requirement is as follows. I have a DataGrid and to input data into the DataGrid, I want a panel at the bottom of the DataGrid that slides out on a button click showing input options. Except, as the panel slides out, the DataGrid has to resize vertically as well. Can someone throw some light on how I can implement this?
You should be able to use a StackPanel with 2 children, your grid and your panel. Set the initial height of your panel to 0. Once the button is clicked, set the height to whatever you need it to be (e.g., MyPanel.Height = 20). You might want to wrap the grid in a ScrollViewer in case that is needed.
<StackPanel Orientation="Vertical">
<ScrollViewer Height="Auto" VerticalAlignment="Stretch">
<Grid Height="*" VerticalAlignment="Stretch" />
</ScrollViewer>
<ContentControl x:Name="MyPanel" Height="0" />
</StackPanel>
You might need to experiment with VerticalAlignment and Height="Auto" or Height="0" to get the layout you want.
You can use Expander. Please look at the following code snippet.
<DockPanel>
<Expander DockPanel.Dock="Bottom">
<StackPanel>
<TextBlock Height="25"></TextBlock>
<TextBlock Height="25"></TextBlock>
<TextBlock Height="25"></TextBlock>
</StackPanel>
</Expander>
<Border BorderBrush="LightGreen" BorderThickness="2">
<DataGrid/>
</Border>
</DockPanel >

Categories