This is how it looks like right now:
and this is how I'd like to have it:
As shown the tiles should be apposed as densely as possible with only a set margin between them.
And here's my code:
<Grid Background="Gray">
<TextBox x:Name="BoardNameTextBox" HorizontalAlignment="Left" Height="23" Margin="40,3,0,0" TextWrapping="Wrap" Text="pol" VerticalAlignment="Top" Width="120"/>
<Button Content="Button" HorizontalAlignment="Left" Margin="491,3,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
<Grid Margin="0,30,0,0" Background="WhiteSmoke">
<WrapPanel VerticalAlignment="Top" HorizontalAlignment="Left">
<WrapPanel.Resources>
<Style TargetType="{x:Type Rectangle}">
<Setter Property="Width" Value="80" />
<Setter Property="Height" Value="80" />
<Setter Property="Margin" Value="3" />
<Setter Property="Fill" Value="#4DB4DD" />
</Style>
</WrapPanel.Resources>
<Rectangle Width="150" />
<Rectangle />
<Rectangle />
<Rectangle />
<Rectangle Width="200"/>
<Rectangle Height="25"/>
<Rectangle Height="40"/>
<Rectangle />
<Rectangle Width="220"/>
<Rectangle Height="30"/>
<Rectangle Height="30"/>
<Rectangle Width="150" />
<Rectangle />
</WrapPanel>
</Grid>
</Grid>
The code is of course a sample code for my particular problem - later on it should just be a wrap panel (or any other control) with the items (which are custom controls) added programmatically (like "WrapPanel1.Children.Add(r);"). I hope the images are self-explanatory.
What you are looking for is called cascading layout.it has a very popular implementation in javascript called Masonry which has a WPF counterpart known as WPF-Masonry .check preceding links for detail and demo.
Related
I’m building a MVVM app using .Net 4.7.2 that works like a wizard (based on https://www.codeproject.com/KB/WPF/InternationalizedWizard.aspx?display=Print), so no additional frameworks, just the RelayCommand class, a MainWindow.cs that hosts the Main view (the view that has navigation items of the wizard on the left side, and the right side area that hosts the subviews which display based on the stage of the wizard).
Mi issue is that one of my users is experiencing a very strange behaviour with the controls. This is a sample photo of what the application should look like:
And this is a sample photo of what happens to the user. Notice that the image on the bottom left disappears, the bar on the bottom left also disappears, the heading and top text have moved up and clipped inside the window, and the rest of the content in the right side disappears.
Similar to the base InternationalizedWizard App I placed the controls in a grid that has horizontal + vertical alignment set to stretch. The
<Border Background="White" Grid.Column="1" Grid.Row="0">
<ScrollViewer>
<HeaderedContentControl Content="{Binding Path=CurrentPage}" Header="{Binding Path=CurrentPage.DisplayName}" />
</ScrollViewer>
</Border>
I applied this style to the HeaderedContentControl:
<Style TargetType="{x:Type HeaderedContentControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type HeaderedContentControl}">
<StackPanel Margin="2,0">
<Grid Margin="1,1,1,12" RenderTransformOrigin="0.5,0.5">
<Rectangle Fill="{DynamicResource {x:Static SystemColors.AppWorkspaceBrushKey}}" Height="3" Margin="10,-4" Opacity="0.6" RadiusX="8" RadiusY="8" VerticalAlignment="Bottom" />
<ContentPresenter ContentSource="Header" TextBlock.FontSize="22" TextBlock.FontWeight="DemiBold" TextBlock.Foreground="Black" HorizontalAlignment="Center" VerticalAlignment="Center" OpacityMask="Black" />
<Grid.Effect>
<DropShadowEffect Opacity="0.1" />
</Grid.Effect>
<Grid.RenderTransform>
<RotateTransform Angle="0" />
</Grid.RenderTransform>
</Grid>
<Grid>
<Rectangle Fill="{TemplateBinding Background}" />
<ContentPresenter ContentSource="Content" />
</Grid>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The scrollviewer only scrolls up and down if the content is large, but in this case the content should fit fine so as expected the user won't see the scrollviewer.
The image from the bottom left that strangely disappear was placed in the column 0, row 0 of the grid a custom margin so it remains in that area:
<Image Grid.Column="0" Grid.Row="0" Source="..\Assets\SplashLogo.png" HorizontalAlignment="Center" VerticalAlignment="Bottom" Stretch="None" Margin="20,20,20,20"/>
The first page (e.g. Welcome) that displays has another grid with two
<Grid>
<Grid.RowDefinitions>
<RowDefinition MinHeight="30" MaxHeight="60"/>
<RowDefinition Height="*" MinHeight="200"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="{x:Static res:Strings.SomeText_Description}" FontSize="15" FontWeight="Light" Margin="20,0,20,0" TextWrapping="Wrap" />
<StackPanel Grid.Row="1" Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center">
<Label Content="{x:Static res:Strings.WelcomeView_SomeText}" FontSize="15" FontWeight="Light" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="20,0,20,0" />
<TextBox Text="{Binding Path=SomeInput, UpdateSourceTrigger=PropertyChanged}" Height="25" Width="200" FontSize="15" FontWeight="Light" HorizontalAlignment="Left">
<TextBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding MoveNextFromWelcomeCommand}" CommandParameter="{Binding Path=Text, RelativeSource={RelativeSource AncestorType={x:Type TextBox}}}" />
</TextBox.InputBindings>
</TextBox>
</StackPanel>
</Grid>
But the contents of the stack panel completely disappear of view.
Finally, the bottom area of the main view is created in a border like this one, which also completely disappears from view:
<Border Grid.Column="0" Grid.Row="1" Background="LightGray" Grid.ColumnSpan="2">
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="5" Margin="4" FontSize="15" Text="{Binding Path=ReportStatus}" VerticalAlignment="Center" Visibility="{Binding Path=ShowReportStatus}" />
<!-- NAVIGATION BUTTONS -->
<Grid Grid.Column="2" Grid.Row="0" Grid.IsSharedSizeScope="True" HorizontalAlignment="Right" >
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="Buttons" />
<ColumnDefinition SharedSizeGroup="Buttons" />
<ColumnDefinition SharedSizeGroup="Buttons" />
<ColumnDefinition SharedSizeGroup="Buttons" />
</Grid.ColumnDefinitions>
<Button Grid.Column="1" Grid.Row="0" Command="{Binding Path=MovePreviousCommand}" Style="{StaticResource movePreviousButtonStyle}" />
<Button Grid.Column="2" Grid.Row="0" Command="{Binding Path=MoveNextCommand}" Style="{StaticResource moveNextButtonStyle}" />
<Button Grid.Column="3" Grid.Row="0" Command="{Binding Path=CancelCommand}" Style="{StaticResource cancelButtonStyle}" />
</Grid>
</Grid>
</Border>
I initially thought there could be an issue with the version of .NET or OS, but my users has the latest version of Windows 10 Enterprise (10.0.17134) and dual screen with 1: 3840x2160 2: 2560x1600. I have tried to replicate that on my own computer but everything works fine for me. I also tested the App in Windows 7 and it works with no issues.
I really don't understand what could be happening, does it have anything to do with the user's DPI settings or any accessibility feature?
EDIT:
To make things a bit easier, this is the full code of the main view's xaml:
<UserControl x:Class="MyCompany.MyAppName.App.View.MyAppView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MyCompany.MyAppName.App.View"
xmlns:viewModel="clr-namespace:MyCompany.MyAppName.App.ViewModel"
xmlns:view="clr-namespace:MyCompany.MyAppName.App.View"
xmlns:res="clr-namespace:MyCompany.MyAppName.App.Assets"
xmlns:util="clr-namespace:MyCompany.MyAppName.App.Utils"
mc:Ignorable="d"
x:Name="configuratorControl" d:DesignHeight="600" d:DesignWidth="600"
>
<UserControl.Resources>
<util:PercentageConverter x:Key="percentageConverter"/>
<DataTemplate DataType="{x:Type viewModel:ObjectSelectionViewModel}">
<view:ObjectSelectionPageView/>
</DataTemplate>
<DataTemplate DataType="{x:Type viewModel:CurrentObjectComponentsViewModel}">
<view:CurrentObjectComponentsView/>
</DataTemplate>
<DataTemplate DataType="{x:Type viewModel:CurrentObjectOptionsViewModel}">
<view:CurrentObjectOptionsView/>
</DataTemplate>
<DataTemplate DataType="{x:Type viewModel:SageFourViewModel}">
<view:SageFourView/>
</DataTemplate>
<DataTemplate DataType="{x:Type viewModel:SageThreeViewModel}">
<view:SageThreeView/>
</DataTemplate>
<DataTemplate DataType="{x:Type viewModel:ObjectViewModel}">
<view:MyNumberView/>
</DataTemplate>
<Style TargetType="{x:Type Button}">
<Setter Property="Padding" Value="3.5,0" />
<Setter Property="Margin" Value="3.5" />
<Setter Property="MinWidth" Value="80" />
<Setter Property="FontSize" Value="15"/>
<Setter Property="FontWeight" Value="Regular"/>
</Style>
<!-- This Style inherits from the Button style seen above. -->
<Style BasedOn="{StaticResource {x:Type Button}}" TargetType="{x:Type Button}" x:Key="moveNextButtonStyle">
<Setter Property="Content" Value="{x:Static res:Strings.MyAppView_Button_MoveNext}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsOnLastPage}" Value="True">
<Setter Property="Content" Value="{x:Static res:Strings.SageThreeView_Confirm}" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=IsOnCreateSageThreePage}" Value="True">
<Setter Property="Content" Value="{x:Static res:Strings.MyAppView_Button_CreateSageThree}" />
</DataTrigger>
</Style.Triggers>
</Style>
<Style BasedOn="{StaticResource {x:Type Button}}" TargetType="{x:Type Button}" x:Key="cancelButtonStyle">
<Setter Property="Content" Value="{x:Static res:Strings.MyAppView_Button_Cancel}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsOnLastPage}" Value="True">
<Setter Property="Content" Value="{x:Static res:Strings.MyAppView_Button_ExportPDF}" />
</DataTrigger>
</Style.Triggers>
</Style>
<Style BasedOn="{StaticResource {x:Type Button}}" TargetType="{x:Type Button}" x:Key="movePreviousButtonStyle">
<Setter Property="Content" Value="{x:Static res:Strings.MyAppView_Button_MovePrevious}" />
</Style>
<!-- HEADERED CONTENT CONTROL STYLE -->
<Style TargetType="{x:Type HeaderedContentControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type HeaderedContentControl}">
<StackPanel Margin="2,0">
<Grid Margin="1,1,1,12" RenderTransformOrigin="0.5,0.5">
<Rectangle Fill="{DynamicResource {x:Static SystemColors.AppWorkspaceBrushKey}}" Height="3" Margin="10,-4" Opacity="0.6" RadiusX="8" RadiusY="8" VerticalAlignment="Bottom" />
<ContentPresenter ContentSource="Header" TextBlock.FontSize="22" TextBlock.FontWeight="DemiBold" TextBlock.Foreground="Black" HorizontalAlignment="Center" VerticalAlignment="Center" OpacityMask="Black" />
<Grid.Effect>
<DropShadowEffect Opacity="0.1" />
</Grid.Effect>
<Grid.RenderTransform>
<RotateTransform Angle="0" />
</Grid.RenderTransform>
</Grid>
<Grid>
<Rectangle Fill="{TemplateBinding Background}" />
<ContentPresenter ContentSource="Content" />
</Grid>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<DataTemplate x:Key="workflowStepTemplate">
<Border x:Name="bdOuter" BorderBrush="Black" BorderThickness="0,0,1,1" CornerRadius="12" Margin="1,1,1,12" Opacity="0.25" SnapsToDevicePixels="True">
<Border x:Name="bdInner" Background="White" BorderBrush="DarkBlue" BorderThickness="2,2,1,1" CornerRadius="12" Padding="2">
<TextBlock x:Name="txt" Margin="4,0,0,0" FontSize="15" FontWeight="Light" Text="{Binding Path=DisplayName}" />
</Border>
</Border>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=IsCurrentPage}" Value="True">
<Setter TargetName="txt" Property="FontWeight" Value="SemiBold" />
<Setter TargetName="bdInner" Property="Background" Value="White" />
<Setter TargetName="bdOuter" Property="Opacity" Value="1" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</UserControl.Resources>
<Canvas HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="{Binding ActualWidth, ElementName=configuratorControl}" Height="{Binding ActualHeight, ElementName=configuratorControl}">
<Canvas x:Name="searchCanvas" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Panel.ZIndex="3" Width="{Binding ActualWidth, ElementName=configuratorControl}" Height="{Binding ActualHeight, ElementName=configuratorControl}" Visibility="{Binding SearchBoxVisibility}">
<Grid Panel.ZIndex="4" Width="{Binding ActualWidth, ElementName=searchCanvas}" Height="{Binding ActualHeight, ElementName=searchCanvas}">
<StackPanel Panel.ZIndex="4" Orientation="Vertical" Width="270" Height="70" VerticalAlignment="Center" HorizontalAlignment="Center" >
<StackPanel Orientation="Horizontal" >
<TextBlock Margin="5" FontSize="15" Text="Serial Number:" Width="100" Height="25" TextAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" />
<TextBox Text="{Binding MyNumber, UpdateSourceTrigger=PropertyChanged}" Margin="5" Width="150" Height="25" />
</StackPanel>
<DockPanel HorizontalAlignment="Stretch">
<Button Margin="5" Content="Dismiss" Width="100" HorizontalAlignment="Left" Command="{Binding DismissSearchDraftCommand}"/>
<Button Margin="5" Content="Search" Width="100" HorizontalAlignment="Right" Command="{Binding StartSearchDraftCommand}"/>
</DockPanel>
</StackPanel>
<Rectangle Panel.ZIndex="3" Fill="LightBlue" Width="300" Height="100" />
</Grid>
<Rectangle Panel.ZIndex="2" Fill="LightGray" Opacity="0.4" Canvas.Left="0" Canvas.Top="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="{Binding ActualWidth, ElementName=configuratorControl}" Height="{Binding ActualHeight, ElementName=configuratorControl}" />
</Canvas>
<Grid Background="#11000000" Margin="1" Panel.ZIndex="2" IsEnabled="{Binding GridResultsEnabled}" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Height="{Binding ActualHeight, ElementName=configuratorControl, Converter={StaticResource percentageConverter}, ConverterParameter=99.5}" Width="{Binding ActualWidth, ElementName=configuratorControl, Converter={StaticResource percentageConverter}, ConverterParameter=99.5}">
<Grid.BitmapEffect>
<BlurBitmapEffect Radius="{Binding GridBoxBlur}" KernelType="Box" />
</Grid.BitmapEffect>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="220" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="60" />
</Grid.RowDefinitions>
<!-- Workflow step listing -->
<HeaderedContentControl Header="{x:Static res:Strings.MyAppView_HeaderSteps}">
<ItemsControl ItemsSource="{Binding Path=Pages}" ItemTemplate="{StaticResource workflowStepTemplate}" />
</HeaderedContentControl>
<Button FontSize="15" Style="{StaticResource HyperLinkButtonStyle}" Margin="20,20,20,140" VerticalAlignment="Bottom" HorizontalAlignment="Center" Content="{x:Static res:Strings.MyAppView_Button_Search_Full}" Command="{Binding Path=OpenSearchFullCommand}"/>
<Button FontSize="15" Style="{StaticResource HyperLinkButtonStyle}" Margin="20,20,20,170" VerticalAlignment="Bottom" HorizontalAlignment="Center" Content="{x:Static res:Strings.MyAppView_Button_Search_Draft}" Command="{Binding Path=OpenSearchDraftCommand}"/>
<Button Margin="20,295,20,20" Command="{Binding Path=StartAgainCommand}" Content="{x:Static res:Strings.SageThreeView_StartAgain}" VerticalAlignment="Top" />
<Image Grid.Column="0" Grid.Row="0" Source="..\Assets\SplashLogo.png" HorizontalAlignment="Center" VerticalAlignment="Bottom" Stretch="None" Margin="20,20,20,20"/>
<!-- CURRENT PAGE AREA -->
<Border Background="White" Grid.Column="1" Grid.Row="0">
<ScrollViewer>
<HeaderedContentControl Content="{Binding Path=CurrentPage}" Header="{Binding Path=CurrentPage.DisplayName}" />
</ScrollViewer>
</Border>
<Border Grid.Column="0" Grid.Row="1" Background="LightGray" Grid.ColumnSpan="2">
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="5" Margin="4" FontSize="15" Text="{Binding Path=SageThreeStatus}" VerticalAlignment="Center" Visibility="{Binding Path=ShowSageThreeStatus}" />
<!-- NAVIGATION BUTTONS -->
<Grid Grid.Column="2" Grid.Row="0" Grid.IsSharedSizeScope="True" HorizontalAlignment="Right" >
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="Buttons" />
<ColumnDefinition SharedSizeGroup="Buttons" />
<ColumnDefinition SharedSizeGroup="Buttons" />
<ColumnDefinition SharedSizeGroup="Buttons" />
</Grid.ColumnDefinitions>
<Button Grid.Column="1" Grid.Row="0" Command="{Binding Path=MovePreviousCommand}" Style="{StaticResource movePreviousButtonStyle}" />
<Button Grid.Column="2" Grid.Row="0" Command="{Binding Path=MoveNextCommand}" Style="{StaticResource moveNextButtonStyle}" />
<Button Grid.Column="3" Grid.Row="0" Command="{Binding Path=CancelCommand}" Style="{StaticResource cancelButtonStyle}" />
</Grid>
</Grid>
</Border>
</Grid>
</Canvas>
</UserControl>
I've created a customwindow template by redefining it, and inheriting from window. This template resides in a separate class library, and i build a dll and reference it from my main project.
This is a part of code from custom window xaml:
<!-- Window style -->
<Style TargetType="{x:Type local:CustomWindow}">
<Setter Property="WindowStyle" Value="None"/>
<Setter Property="ResizeMode" Value="NoResize"/>
<Setter Property="Background" Value="White"/>
<Setter Property="AllowsTransparency" Value="True"/>
<Setter Property="Opacity" Value="1" />
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush" Value="Silver"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:CustomWindow}">
<Border BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}">
<Grid>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Rectangle x:Name="moveRectangle" Fill="#24282A"
Grid.Row="0" Grid.Column="1"/>
<Label x:Name="WindowName" Background="#24282A" Foreground="White" Grid.Row="0" Grid.Column="0"/>
<StackPanel Grid.Row="0" Grid.Column="2" Orientation="Horizontal" Background="#24282A">
<Button x:Name="minimizeButton" Style="{StaticResource WindowButtonStyle}"
Content="0" />
<Button x:Name="restoreButton" Style="{StaticResource WindowButtonStyle}"
Content="1" />
<Button x:Name="closeButton" Style="{StaticResource WindowButtonStyle}"
Content="r" />
</StackPanel>
<Grid Background="#24282A" Opacity="0.9"
Grid.Row="1" Grid.ColumnSpan="3" Margin="5,0,5,5">
<AdornerDecorator>
<ContentPresenter/>
</AdornerDecorator>
</Grid>
</Grid>
<Grid x:Name="resizeGrid">
<Rectangle
Stroke="{x:Null}"
Fill="#24282A"
VerticalAlignment="Top"
Height="5"
x:Name="top"
Margin="5,0,5,0" />
<Rectangle
Stroke="{x:Null}"
Fill="#24282A"
x:Name="bottom"
Height="5"
VerticalAlignment="Bottom"
Margin="5,0,5,0" />
<Rectangle
Stroke="{x:Null}"
Fill="#24282A"
HorizontalAlignment="Left"
Margin="0,5,0,5"
Width="5"
x:Name="left"/>
<Rectangle
Stroke="{x:Null}"
Fill="#24282A"
Margin="0,5,0,5"
Width="5"
HorizontalAlignment="Right"
x:Name="right" />
<Rectangle
Stroke="{x:Null}"
Fill="#24282A"
HorizontalAlignment="Left"
VerticalAlignment="Bottom"
Width="5"
Height="5"
x:Name="bottomLeft" />
<Rectangle
Stroke="{x:Null}"
Fill="#24282A"
VerticalAlignment="Bottom"
Height="5"
Width="5"
HorizontalAlignment="Right"
x:Name="bottomRight" />
<Rectangle
Stroke="{x:Null}"
Fill="#24282A"
HorizontalAlignment="Right"
Width="5"
Height="5"
VerticalAlignment="Top"
x:Name="topRight" />
<Rectangle
Stroke="{x:Null}"
Fill="#24282A"
HorizontalAlignment="Left"
Width="6"
VerticalAlignment="Top"
Height="5"
x:Name="topLeft" />
</Grid>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
As you can see, there is a label called "WindowName". i want this label to be kind of Title bar in my custom window, and i wanna call it's property content from my main wpf application which inherits from this custom window. Everything works ok, except i have no idea how i should call this label to set it's content. Any help would be appreciated
You would want to bind the content of that Label to the Title property of the base Window class since the base class already has a dependency property that you can just reuse. All you will need to do is update the xaml for you label component as below:
<Label x:Name="WindowName" Content={TemplateBinding Title} Background="#24282A" Foreground="White" Grid.Row="0" Grid.Column="0"/>
You could also override OnApplyTemplate in your CustomWindow and use a method like FindName to get the Label using its name and then updating it through a direct reference, but the binding way is much cleaner so I wouldn't consider that route although I wanted to at least mention it.
I'd like to create a dotted progress bar and I hope someone here can help me with the implementation. It should look something like the following sketch, but with black background. The progress is visualized using circles that change from gray to white when a certain percentage is reached. Ideally the number of dots should dynamically adjust to the bar's width.
+--------------------------------------------------+
| O O O O O O O O O O |
+--------------------------------------------------+
Can this be done using styles alone or do I have to create a custom control?
As Chris W says in the comments, there are a few ways to approach this through styling and templating alone. Here's an example:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Window.Resources>
<Style TargetType="{x:Type ProgressBar}">
<Style.Resources>
<Style x:Key="NormalDot" TargetType="{x:Type Ellipse}">
<Setter Property="Margin" Value="4" />
<Setter Property="Width" Value="10" />
<Setter Property="Height" Value="10" />
<Setter Property="Fill" Value="Gray" />
</Style>
<Style x:Key="ProgressDot" BasedOn="{StaticResource NormalDot}"
TargetType="{x:Type Ellipse}">
<Setter Property="Fill" Value="White" />
</Style>
</Style.Resources>
<Setter Property="Background" Value="Black" />
<Setter Property="Height" Value="18" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ProgressBar}">
<Grid Background="{TemplateBinding Background}">
<StackPanel x:Name="PART_Track" Orientation="Horizontal"
HorizontalAlignment="Left" VerticalAlignment="Center">
<Ellipse Style="{StaticResource NormalDot}" />
<Ellipse Style="{StaticResource NormalDot}" />
<Ellipse Style="{StaticResource NormalDot}" />
<Ellipse Style="{StaticResource NormalDot}" />
<Ellipse Style="{StaticResource NormalDot}" />
<Ellipse Style="{StaticResource NormalDot}" />
<Ellipse Style="{StaticResource NormalDot}" />
<Ellipse Style="{StaticResource NormalDot}" />
<Ellipse Style="{StaticResource NormalDot}" />
<Ellipse Style="{StaticResource NormalDot}" />
<Ellipse Style="{StaticResource NormalDot}" />
<Ellipse Style="{StaticResource NormalDot}" />
<Ellipse Style="{StaticResource NormalDot}" />
<Ellipse Style="{StaticResource NormalDot}" />
<Ellipse Style="{StaticResource NormalDot}" />
<Ellipse Style="{StaticResource NormalDot}" />
<Ellipse Style="{StaticResource NormalDot}" />
<Ellipse Style="{StaticResource NormalDot}" />
<Ellipse Style="{StaticResource NormalDot}" />
<Ellipse Style="{StaticResource NormalDot}" />
</StackPanel>
<StackPanel x:Name="PART_Indicator" Orientation="Horizontal"
HorizontalAlignment="Left" VerticalAlignment="Center">
<Ellipse Style="{StaticResource ProgressDot}" />
<Ellipse Style="{StaticResource ProgressDot}" />
<Ellipse Style="{StaticResource ProgressDot}" />
<Ellipse Style="{StaticResource ProgressDot}" />
<Ellipse Style="{StaticResource ProgressDot}" />
<Ellipse Style="{StaticResource ProgressDot}" />
<Ellipse Style="{StaticResource ProgressDot}" />
<Ellipse Style="{StaticResource ProgressDot}" />
<Ellipse Style="{StaticResource ProgressDot}" />
<Ellipse Style="{StaticResource ProgressDot}" />
<Ellipse Style="{StaticResource ProgressDot}" />
<Ellipse Style="{StaticResource ProgressDot}" />
<Ellipse Style="{StaticResource ProgressDot}" />
<Ellipse Style="{StaticResource ProgressDot}" />
<Ellipse Style="{StaticResource ProgressDot}" />
<Ellipse Style="{StaticResource ProgressDot}" />
<Ellipse Style="{StaticResource ProgressDot}" />
<Ellipse Style="{StaticResource ProgressDot}" />
<Ellipse Style="{StaticResource ProgressDot}" />
<Ellipse Style="{StaticResource ProgressDot}" />
</StackPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<ProgressBar Value="{Binding Value, ElementName=_slider}"
VerticalAlignment="Top" />
<Slider x:Name="_slider" Minimum="0" Maximum="100"
VerticalAlignment="Bottom" />
</Grid>
</Window>
The basic idea is two StackPanel containers, each holding ten Ellipse elements. The second StackPanel is layered over the first using a Grid, however its width varies in line with the progress bar's current value, which then gives the desired effect of the white "dots" appearing as progress increases. If you wanted a different number of dots then you'd increase or decrease the number of Ellipse elements: just remember you need the same number in each panel.
A variation of this technique would replace the ItemsControls, StackPanels and Ellipses with a pair of Rectangle elements filled with custom DrawingBrushes.
The weakness of both approaches given your stated requirements is that (a) you don't get any animation effect, and (b) you get partially-filled ellipses. You could mitigate (b) by limiting the values of the progress bar in code (ie. round to nearest x%), however to solve (a) I think you'd be looking at a new control subclassed from the existing ProgressBar.
I want to make a UserControl like this image;
There are 9 boxes, top one is for rotating, while other one is for scaling purposes. I tried to make this with grid and background image, 2 rows, and small boxes with StackPanel, but have to provide lots of negative and positive margins to achieve this result. Is there any easy way to do so need help.
Thanks.
Something like this?
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid.RowDefinitions>
<RowDefinition Height="25"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.Resources>
<Style TargetType="Rectangle">
<Setter Property="Stroke" Value="Black"/>
<Setter Property="StrokeThickness" Value="1"/>
<Setter Property="Height" Value="11"/>
<Setter Property="Width" Value="11"/>
<!-- For hittestvisibility -->
<Setter Property="Fill" Value="Transparent"/>
</Style>
</Grid.Resources>
<Line X1="0" Y1="1" X2="0" Y2="0" Stretch="Fill" Stroke="Black" />
<Rectangle VerticalAlignment="Top" HorizontalAlignment="Center"/>
<Grid Grid.Row="1" Height="200" Width="200" Margin="-5">
<Rectangle Margin="5" Height="Auto" Width="Auto" Fill="{x:Null}"/>
<Rectangle VerticalAlignment="Top" HorizontalAlignment="Left"/>
<Rectangle VerticalAlignment="Top" HorizontalAlignment="Center"/>
<Rectangle VerticalAlignment="Top" HorizontalAlignment="Right"/>
<Rectangle VerticalAlignment="Center" HorizontalAlignment="Left"/>
<Rectangle VerticalAlignment="Center" HorizontalAlignment="Right"/>
<Rectangle VerticalAlignment="Bottom" HorizontalAlignment="Left"/>
<Rectangle VerticalAlignment="Bottom" HorizontalAlignment="Center"/>
<Rectangle VerticalAlignment="Bottom" HorizontalAlignment="Right"/>
<!-- The Content -->
<Rectangle Width="Auto" Height="Auto" Margin="20" Fill="Green"/>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"
Text="Content"/>
</Grid>
</Grid>
The terminology is Bounding Box
I'm having this annoying problem with WPF that I can't get my head around.
What I'm trying to create, is a very basic implementation of a drawing program (it's a school assignment) with movable tool windows, like in Photoshop.
I've managed to figure out that I can use this element "Thumb" to implement simple Drag functionality. Since the Thumb element itself is not visible, and the object that I'm using as a container (a DockPanel) does not have a DragDelta property, I simply created a ControlTemplate and attached it to the Thumb, so now I have a draggable color picker that works okay. So far so good.
But, problems arise when I want to create additional ControlTemplates, to use for other Thumb-elements that I plan to use (I get the error: The property 'VisualTree' is set more than once.).
This is what I want help with. I have pasted my whole Window.Resources-tag here so you can see what's going on.
<Window.Resources>
<Style x:Key="toolBoxBtn" TargetType="Button">
<Setter Property="Width" Value="60" />
<Setter Property="Height" Value="60" />
<Setter Property="Margin" Value="5" />
<Setter Property="DockPanel.Dock" Value="Top" />
</Style>
<Style x:Key="style1" TargetType="{x:Type Thumb}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<DockPanel Background="#e6e6e6" HorizontalAlignment="Left" Margin="0" Height="auto" Width="auto" Canvas.Left="640" Canvas.Top="8">
<Label VerticalAlignment="Top" DockPanel.Dock="Top" Background="#282828" Foreground="white" Content="Colors" HorizontalAlignment="Stretch" Width="auto" Height="auto" />
<StackPanel>
<StackPanel Orientation="Horizontal" Margin="7" VerticalAlignment="Center">
<Rectangle DockPanel.Dock="top" Name="red" Fill="Red" Height="20" Width="20" Stroke="Black" MouseDown="getColor" />
<Rectangle DockPanel.Dock="top" Name="blue" Fill="Blue" Height="20" Width="20" Stroke="Black" MouseDown="getColor"/>
<Rectangle DockPanel.Dock="top" Name="green" Fill="GreenYellow" Height="20" Width="20" Stroke="Black" MouseDown="getColor"/>
<Rectangle DockPanel.Dock="top" Name="customColorSlot1" Fill="White" Height="20" Width="20" Stroke="Black" MouseDown="getColor" />
<Rectangle DockPanel.Dock="top" Name="customColorSlot2" Fill="White" Height="20" Width="20" Stroke="Black" MouseDown="getColor"/>
<Rectangle DockPanel.Dock="top" Name="customColorSlot3" Fill="White" Height="20" Width="20" Stroke="Black" MouseDown="getColor"/>
</StackPanel>
<GroupBox Header="Selected Color">
<Rectangle Name="currentColor" Fill="White" Height="40" Width="40" Stroke="Black" MouseDown="test"/>
</GroupBox>
</StackPanel>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="fillTool" TargetType="{x:Type Thumb}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Ellipse HorizontalAlignment="Left" Height="19" Margin="310,330,0,0" VerticalAlignment="Top" Width="19" Fill="Blue"/>
<Ellipse HorizontalAlignment="Left" Height="12" Margin="317,316,0,0" VerticalAlignment="Top" Width="12" Fill="Blue"/>
<Ellipse HorizontalAlignment="Left" Height="8" Margin="307,320,0,0" VerticalAlignment="Top" Width="7" Fill="Blue"/>
<Ellipse HorizontalAlignment="Left" Height="3" Margin="317,302,0,0" VerticalAlignment="Top" Width="3" Fill="Blue"/>
<Ellipse HorizontalAlignment="Left" Height="5" Margin="311,310,0,0" VerticalAlignment="Top" Width="5" Fill="Blue"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
What could be the problem here?
ControlTemplate can only contain one child. Try and change it to a Canvas instead
<Style x:Key="fillTool" TargetType="{x:Type Thumb}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Canvas>
<Ellipse HorizontalAlignment="Left" Height="19" Margin="310,330,0,0" VerticalAlignment="Top" Width="19" Fill="Blue"/>
<Ellipse HorizontalAlignment="Left" Height="12" Margin="317,316,0,0" VerticalAlignment="Top" Width="12" Fill="Blue"/>
<Ellipse HorizontalAlignment="Left" Height="8" Margin="307,320,0,0" VerticalAlignment="Top" Width="7" Fill="Blue"/>
<Ellipse HorizontalAlignment="Left" Height="3" Margin="317,302,0,0" VerticalAlignment="Top" Width="3" Fill="Blue"/>
<Ellipse HorizontalAlignment="Left" Height="5" Margin="311,310,0,0" VerticalAlignment="Top" Width="5" Fill="Blue"/>
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>