I have a simple UI made with wpf. In there is a Page containig a CustomControl with a TreeView. To reorder the TreeNodes i am using wpf dragdrop. This works pretty well so far. Now i'm playing around with WindowChrome to create a borderless window. But the Problem: Now Drag & Drop won't work. If i try to drag an object the curser changes into a "no valid drop position"
What i've found out: If i delete my custom evererything works. But i have now idea what is missing to get the drag and drop function working with my custom style.
The TreeView:
<TreeView x:Name="StructureTree"
Grid.Row="0"
Padding="10,20,20,0"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
ItemsSource="{Binding Path=RootElement.Children}"
Background="{x:Null}"
BorderBrush="{x:Null}"
dd:DragDrop.IsDragSource="true"
dd:DragDrop.IsDropTarget="true"
dd:DragDrop.UseDefaultDragAdorner="true">
The Window.Resources:
<Window.Resources>
<Style TargetType="{x:Type local:MainWindow}" BasedOn="{StaticResource {x:Type Window}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}">
<!-- Outer border with the dropshadow margin -->
<Border Padding="{Binding OuterMargin, FallbackValue=10}">
<!-- Main window outline -->
<Grid>
<!-- Opacity mask for corners on grid -->
<Border x:Name="Container"
Background="{StaticResource BackgroundVeryLightBrush}"
CornerRadius="{Binding WindowCornerRadius}" />
<!-- Window border and dropshadown -->
<Border CornerRadius="{Binding WindowCornerRadius}"
Background="{Binding BackgroundVeryLightBrush}" BorderBrush="#FF1E1E1E">
<Border.Effect>
<DropShadowEffect ShadowDepth="2" Opacity="0.2" BlurRadius="5" />
</Border.Effect>
<Border.OpacityMask>
<VisualBrush Visual="{Binding ElementName=Container}" />
</Border.OpacityMask>
</Border>
<!-- The main window content -->
<Grid>
<!-- Corner clipping -->
<Grid.OpacityMask>
<VisualBrush Visual="{Binding ElementName=Container}" />
</Grid.OpacityMask>
<Grid.RowDefinitions>
<!-- Title Bar -->
<RowDefinition Height="{Binding TitleHeight, FallbackValue=42}"/>
<!-- Window Content -->
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Title Bar -->
<Grid Grid.Column="0" Grid.Row="0" Panel.ZIndex="1">
<Grid.ColumnDefinitions>
<!-- Icon -->
<ColumnDefinition Width="Auto"/>
<!-- Title -->
<ColumnDefinition Width="*"/>
<!-- Window Buttons -->
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<!-- Icon -->
<Button Margin="1" Padding="0" Style="{StaticResource IconButton}" WindowChrome.IsHitTestVisibleInChrome="True" Command="{Binding MenuCommand}">
<!--<Image Source="/Images/Logo/Icon.ico"/>-->
</Button>
<!-- Title -->
<Viewbox Grid.Column="0" Grid.ColumnSpan="3" Margin="0">
<TextBlock Style="{StaticResource TitleText}"
Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Title, FallbackValue= 'Wellcome'}"/>
</Viewbox>
<!-- Window Buttons -->
<StackPanel Grid.Column="2" Orientation="Horizontal">
<Button Command="{Binding MinimizeCommand}" Style="{StaticResource WindowControlButton}" Content="_"/>
<Button Command="{Binding MaximizeCommand}" Style="{StaticResource WindowControlButton}" Content="[ ]"/>
<Button Command="{Binding CloseCommand}" Style="{StaticResource WindowCloseButton}" Content="X"/>
</StackPanel>
</Grid>
<!-- Page Content -->
<Border Grid.Row="1" Padding="{Binding InnerContentPadding}">
<ContentPresenter Content="{TemplateBinding Content}"/>
</Border>
</Grid>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
When I was experimenting with a similar scenario I found that WPF won't allow to drop an item if it can't detect a control under the cursor. The solution to this may be to add a stretched rectangle "under" your TreeView with transparent filling:
<Rectangle
Fill="Transparent"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"/>
<TreeView x:Name="StructureTree"...
Just so a control could be "under" your cursor and then you should get back your valid drop area.
Edit:
If it doesn't want to work, try to put the rectangle before this part in the template:
<!-- Opacity mask for corners on grid -->
<Border x:Name="Container"
Background="{StaticResource BackgroundVeryLightBrush}"
CornerRadius="{Binding WindowCornerRadius}" />
And since the basic window template uses AdornerDecorator, it's worth a shot to include in your template too, where needed:
<AdornerDecorator>
<ContentPresenter.../>
</AdornerDecorator>
Related
I have a grid with one row and some columns. In order to scale correctly the grid content according to the screen resolution and scale selected in the Windows OS, I use a Viewbox.
I also define a style that is applied to all Viewboxes:
<Style TargetType="{x:Type Viewbox}">
<Setter Property="Stretch" Value="Uniform"/>
<Setter Property="StretchDirection" Value="Both"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="OverridesDefaultStyle" Value="False"/>
<Setter Property="UseLayoutRounding" Value="False"/>
</Style>
And then I enclose every grid column within a Viewbox:
<Grid Focusable="True"
Height="Auto">
<Grid.ColumnDefinitions>
<!-- Animated image -->
<ColumnDefinition Width="Auto" />
<!-- Stack panel with icon and text -->
<ColumnDefinition Width="Auto" />
<!-- A vertical separator -->
<ColumnDefinition Width="Auto" />
<!-- A button -->
<ColumnDefinition Width="Auto" />
<!-- Empty dummy column to help distribute space correctly between columns so it will cause next columns to be horizontally right aligned. -->
<ColumnDefinition Width="*" />
<!-- Help button -->
<ColumnDefinition Width="Auto" />
<!-- Three dots button -->
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Viewbox Grid.Column="0">
<StackPanel Orientation="Horizontal"
Visibility="{Binding Path=IsAnimatedImgVisible, Converter={StaticResource BoolToVisibility}}">
<v:UserControlAnimatedImg x:Name="UcSpinner" VerticalAlignment="Center" HorizontalAlignment="Left"/>
<Label SnapsToDevicePixels="True"
RenderOptions.BitmapScalingMode="HighQuality"
VerticalAlignment="Center" HorizontalAlignment="Left"
Content="{Binding Path=StatusText}"/>
</StackPanel>
</Viewbox>
<Viewbox Grid.Column="1">
<StackPanel Orientation="Horizontal">
<Image
Margin="10,5"
Height="24"
Width="24"
MaxHeight="24"
MaxWidth="24"
VerticalAlignment="Center"
HorizontalAlignment="Center"
SnapsToDevicePixels="True"
RenderOptions.BitmapScalingMode="HighQuality"
Source="{Binding Path=Icon}"/>
<Label
VerticalAlignment="Center"
HorizontalAlignment="Left"
Content="{Binding Path=StatusTxt}"
SnapsToDevicePixels="True"
RenderOptions.BitmapScalingMode="HighQuality">
</Label>
</StackPanel>
</Viewbox>
<Viewbox Grid.Column="2">
<Separator Margin="10,5,5,5"
Height="26"
Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}">
</Viewbox>
<Viewbox Grid.Column="3">
<Button Height="Auto"
Width="150"
Command="{Binding ButtonOnClick}">
<StackPanel Orientation="Horizontal">
<Image
Height="24"
Width="25"
MaxHeight="24"
MaxWidth="25"
VerticalAlignment="Center"
HorizontalAlignment="Center"
SnapsToDevicePixels="True"
RenderOptions.BitmapScalingMode="HighQuality"
Source="{Binding ImageIcon}"/>
<TextBlock
Margin="10,2,5,2"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Text="{x:Static p:Resources.BtnText}"
SnapsToDevicePixels="True"
RenderOptions.BitmapScalingMode="HighQuality">
</TextBlock>
</StackPanel>
</Button>
</Viewbox>
<!-- Empty dummy space to help distribute space correctly between columns and
make next columns to be horizontally right aligned. This column will be blank
space.-->
<Viewbox Grid.Column="4">
<ContentControl />
</Viewbox>
<Viewbox Grid.Column="5">
<Button Height="25"
Width="25"
MaxHeight="25"
MaxWidth="25"
Margin="8,0,5,0"
Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}"
Command="{Binding BtnHlpClick}">
<Image HorizontalAlignment="Center"
VerticalAlignment="Center"
SnapsToDevicePixels="True"
RenderOptions.BitmapScalingMode="HighQuality"
Source="{Binding ImageHelpIcon}"/>
</Button>
</Viewbox>
<Viewbox Grid.Column="6">
<StackPanel x:Name="PlaceHolder"
VerticalAlignment="Center"
Margin="2,0,12,0"
Width="27"
Height="Auto">
<Image HorizontalAlignment="Center"
VerticalAlignment="Center"
Height="20"
Width="20"
SnapsToDevicePixels="True"
RenderOptions.BitmapScalingMode="HighQuality"
Source="{Binding ImgThreeDotsIcon}">
<Image.ContextMenu>
<ContextMenu Placement="Bottom" Background="#FFFFFF">
<MenuItem Header="{x:Static p:Resources.mnutext}" Command="{Binding MenuOnClick}"></MenuItem>
</ContextMenu>
</Image.ContextMenu>
</Image>
</StackPanel>
</Viewbox>
The problem I am currently facing is that when I switch to high screen resolutions and also I switch to high scale factor (125%, 150%, 175%, 200%, and so on), then the content of the grid is getting smaller and smaller and it is practically impossible to see. The more screen resolution I select, the more smaller is the grid content. The more scale factor I select, the more smaller is the grid content. The problem is that the grid content gets too small and impossible to see.
How can I solve this?
I have created a custom control for the simplified usage of label: control in forms:
My problem is that, no matter what is being put into my control content, I am unable to align it, using my template code. The only way it works is when I put HorizontalAlignment="Right" into the TextBox control directly:
<local:ControlEntry Label="Enter something">
<!-- I don't like having HorizontalAlignment here! -->
<TextBox Height="20" Width="200" HorizontalAlignment="Right" />
</local:ControlEntry>
However, I would rather want to do that behind the scenes in my control template.
I'm talking about this particular XAML code:
<Border x:Name="Container"
HorizontalAlignment="Stretch"
Grid.Column="1">
<ContentPresenter Width="{Binding ActualWidth, ElementName=Container}" HorizontalAlignment="Right" />
</Border>
First, I stretch the HorizontalAlignment, so what it would fill the width of the grid column cell, then I'm trying to apply the Right HorizontalAlignment on the ContentPresenter. Unfortunately, no effect is visible.
Full control code:
<Style TargetType="{x:Type local:ControlLine}">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:ControlLine}">
<!-- Create bottom content border -->
<Border BorderBrush="#000" BorderThickness="0,0,0,0.5">
<StackPanel>
<Grid>
<!-- Label -> Control -->
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- Label -->
<TextBlock Grid.Column="0"
Margin="0,12,15,12"
VerticalAlignment="Center"
Text="{Binding Label, RelativeSource={RelativeSource TemplatedParent}}"
TextWrapping="WrapWithOverflow" />
<!-- Display content -->
<Border x:Name="Container"
HorizontalAlignment="Stretch"
Grid.Column="1">
<ContentPresenter Width="{Binding ActualWidth, ElementName=Container}" HorizontalAlignment="Right" />
</Border>
</Grid>
<!-- Description -->
<TextBlock Text="The control description" />
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
How can I properly keep the width stretched and at the same time align the content of ContentPresenter to right?
In my MainWindow I have defined a region, that I am injecting my UserControls into (using Prism, but it doesn't matter). My control should be resizeable (it works perfectly) and moveable. To drag and move my user control I am using Blend's MouseDragElementBehavior. Problem is, that although my control moves, when I resize MainWindow it gets cut :
When I am not moving my control everything works, as expected, when I resize MainWindow scrollBar shows up:
But when I move my user control to the bottom of the MainWindow, the ScrollBar is not showing up like it does't know, that my control has been moved:
Important: The ScrollBar is showing up in both scenarios at exact same time, though when I move my user control down it should appear much more sonner, when I reach the bounds of the user control. On the picture below you can see the moment when the ScrollBar is showing up after I draged my control down. It appeared too late, control gets cut.
It's hard to explain, let me know if you understood me correctly.
My code:
<Window x:Class="ViewInjection.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
Title="MainWindow">
<ScrollViewer HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="*" ScrollViewer.CanContentScroll="True" ScrollViewer.IsDeferredScrollingEnabled="True"/>
</Grid.RowDefinitions>
<Button Grid.Row="0" Click="Button_Click">Add View</Button>
<ItemsControl Grid.Row="1" prism:RegionManager.RegionName="ContentRegion" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
</Grid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</Grid>
</ScrollViewer>
</Window>
UserControl:
<UserControl
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:ViewInjection.Views"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" x:Class="ViewInjection.Views.ViewA"
mc:Ignorable="d">
<Border x:Name="Border" HorizontalAlignment="Center" VerticalAlignment="Center" BorderBrush="#FF626161" BorderThickness="2" CornerRadius="3" MinHeight="200" MinWidth="200">
<i:Interaction.Behaviors>
<ei:MouseDragElementBehavior ConstrainToParentBounds="true"/>
</i:Interaction.Behaviors>
<DockPanel x:Name="sizableContent" Background="LightGray" Focusable="False" LastChildFill="True" MinHeight="300" MinWidth="300">
<DockPanel DockPanel.Dock="Bottom" >
<!--Make user control resizeable-->
<Thumb DockPanel.Dock="Right" VerticalAlignment="Bottom" Margin="0,0,1,1"
DragDelta="OnResizeThumbDragDelta"
DragStarted="OnResizeThumbDragStarted"
DragCompleted="OnResizeThumbDragCompleted">
<Thumb.Style>
<Style TargetType="{x:Type Thumb}">
<Style.Setters>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid x:Name="resizeVisual" DockPanel.Dock="Right" VerticalAlignment="Bottom" >
<Line X1="6" Y1="18" X2="18" Y2="6" Stroke="DarkGray" StrokeThickness="1.5"/>
<Line X1="10" Y1="18" X2="18" Y2="10" Stroke="DarkGray" StrokeThickness="1.5"/>
<Line X1="14" Y1="18" X2="18" Y2="14" Stroke="DarkGray" StrokeThickness="1.5"/>
<Grid.Style>
<Style TargetType="{x:Type Grid}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Cursor" Value="SizeNWSE"/>
</Trigger>
</Style.Triggers>
</Style>
</Grid.Style>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
</Thumb.Style>
</Thumb>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch">
<Button Margin="12" Width="75" TabIndex="1" Content="Ok"/>
</StackPanel>
</DockPanel>
<StackPanel HorizontalAlignment="Center" Margin="16,16,16,4">
<TextBlock Text="My UserControl"/>
</StackPanel>
</DockPanel>
</Border>
</UserControl>
P.S.
I am using items control to have multiple controls within that region. I am using Grid as a template, because I want controls to overlap each other.
I have a TextBlock that dislays a message. I have to build the ability to edit and save this message. When the Edit Icon is clicked, instead of popping up another view with a TextBox and a Save Button, I wanted to somehow just show a Textbox and Save Button in place of the TextBlock. Then when Save is clicked it would change the State back again only showing the read only TextBlock.
I thought that I could do this with the VisualStateManager but it seems you can only do Storyboards for States and even if I leave the button always there and make it invisible I can't seem to change the Property Value between States either.
Is VisualStateManager the answer for this or is there something better to use?
Update
I found and followed this example View / Edit Control and it looks like it will solve my issue.
<UserControl x:Class="WpfApplication1.Test2"
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:c="clr-namespace:WpfApplication1"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Label Name="MyTest" c:ReadOnlyControlTemplate.Enabled="True" c:ReadOnlyControlTemplate.DoLock="False" Grid.Column="0" Grid.Row="0" Content="{Binding Path=Message}" >
<Control.Template>
<ControlTemplate TargetType="{x:Type Label}">
<TextBox Width="{TemplateBinding Property=Width}" Height="{TemplateBinding Property=Height}" Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}" AcceptsReturn="True" Margin="100,0" />
</ControlTemplate>
</Control.Template>
<c:ReadOnlyControlTemplate.LockTemplate>
<ControlTemplate TargetType="{x:Type Label}">
<Border BorderBrush="Red" BorderThickness="3">
<TextBlock Width="{TemplateBinding Property=Width}" Height="{TemplateBinding Property=Height}" Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}" Foreground="White" />
</Border>
</ControlTemplate>
</c:ReadOnlyControlTemplate.LockTemplate>
</Label>
<WrapPanel Grid.Column="0" Grid.Row="1" HorizontalAlignment="Center">
<Button Content="ReadOnly" Width="70" Height="25" Click="Button_Click" Margin="0,0,5,0" />
<Button Content="Edit" Grid.Column="0" Grid.Row="1" Width="50" Height="25" Click="Button_Click2" />
</WrapPanel>
</Grid>
I'm trying to create a Button that contains a grid, with rows that contain certain text.
The Button will have two rows, both with different pieces of text. The text that is passed to the ControlTemplate is showing, but not the text specified in the template.
Also, the heights of the Grid rows is not showing. I want it to expand the height of the button. In fact, I'm not sure that the Grid is showing at all really.
<Window x:Class="MAQButtonTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="695" Width="996">
<Window.Resources>
<Style TargetType="TextBlock">
<Setter Property="OverridesDefaultStyle" Value="True"/>
</Style>
<ControlTemplate TargetType="Control" x:Key="1">
<Grid Width="444">
<Grid.RowDefinitions>
<RowDefinition Height="51" />
<RowDefinition Height="36" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" Background="#286c97">
<TextBlock>This is the first piece of text</TextBlock>
</Grid>
<Grid Grid.Row="1" Background="#5898c0">
<ContentPresenter Grid.Row="0" />
</Grid>
</Grid>
</ControlTemplate>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid Grid.Column="0" Background="#e9f1f6"></Grid>
<Grid Grid.Column="1" Background="#d2e3ed">
<StackPanel>
<TextBlock FontFamily="Segoe UI" FontSize="22" FontWeight="Medium" Margin="52,58,0,0" Foreground="#0c3d5d">Your Quizzes <TextBlock FontFamily="Segoe UI" FontSize="18" FontWeight="Medium" Foreground="#0c3d5d">(7)</TextBlock></TextBlock>
<Grid>
<Button Width="444" Background="{x:Null}" BorderThickness="0" Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}">
<TextBlock>This is a second piece of text</TextBlock>
</Button>
</Grid>
</StackPanel>
</Grid>
</Grid>
</Window>
Here's how it shows at the moment with a rough illustration of what I'm trying to achieve as a button layout:
You're setting the Style of the Button, when you should be setting the Template
Resource:
<ControlTemplate TargetType="Button" x:Key="ButtonTemplate">
<Grid Width="444">
<Grid.RowDefinitions>
<RowDefinition Height="51" />
<RowDefinition Height="36" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" Background="#286c97">
<TextBlock>This is the first piece of text</TextBlock>
</Grid>
<Grid Grid.Row="1" Background="#5898c0">
<ContentPresenter />
</Grid>
</Grid>
</ControlTemplate>
And the button:
<Button Template="{StaticResource ButtonTemplate}" >
Text 2
</Button>
Why are you using TargetType as "Control", use Button. You will need to define a button. Use Blend to edit button template to strip all unnecessary content from it.