I have a DataTemplate like this:
<!-- MULTI VIEW TEMPLATE -->
<DataTemplate x:Key="MultiViewTemplate" >
<Grid x:Name="MultiViewGrid" ShowGridLines="True" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ContentControl Content="{StaticResource BorderHwnd1}" Grid.Column="0" Grid.Row="0" x:Name="MultiViewBorder1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" MouseDoubleClick="MultiViewBorder1_MouseDoubleClick"/>
<ContentControl Content="{StaticResource BorderHwnd2}" Grid.Column="1" Grid.Row="0" x:Name="MultiViewBorder2" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" MouseDoubleClick="MultiViewBorder2_MouseDoubleClick"/>
<ContentControl Content="{StaticResource BorderHwnd3}" Grid.Column="0" Grid.Row="1" x:Name="MultiViewBorder3" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" MouseDoubleClick="MultiViewBorder3_MouseDoubleClick"/>
<ContentControl Content="{StaticResource BorderHwnd4}" Grid.Column="1" Grid.Row="1" x:Name="MultiViewBorder4" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" MouseDoubleClick="MultiViewBorder4_MouseDoubleClick"/>
</Grid>
</DataTemplate>
And the BorderHwnd1 is like this:
<Border x:Key="BorderHwnd1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" BorderBrush="Transparent" BorderThickness="0" Background="Transparent" >
<Image Margin="1" Source="/MyProject;component/Images/No_image_available.png" />
</Border>
My problem is that MultiViewBorder1_MouseDoubleClick event does not work after I remove and assign programmatically a new child to MultiViewBorder1. Initially MultiViewBorder1.Child is an image (No_image_available.png). In my code, I remove the image and assign a new child. This new child is a HwndHost.
Where is my mistake? any help is appreciated!
The child is changing from a WPF Image control....which is able to raise/flow "routed" "mouse" events through the visual tree....to some "hwnd" which you have inside the HwndHost, which is handling raw WIN32 mouses messages....and doesn't route them.
To be able to get mouse activity in your HwndHost into the visual tree, you could use a few different techniques to get them routed.
have an overlayed "transparent" window
handle the "mouse" messages in your WIN32/Hwnd, and then use "delegates" to raise
How can I convert Win32 mouse messages to WPF mouse events?
WPF WIN32 hwndhost WM_MOUSEMOVE WM_MOUSEHOVER
Related
so I'm trying to make a program that allows users to design simple programs using modules with different functions in WPF.
I've created custom controls for my modules that look like this:
<Border Height="75" Width="150" BorderThickness="1" BorderBrush="Black">
<Grid Background="Gray" Height="75" Width ="150">
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="2*"/>
</Grid.RowDefinitions>
<Label Content="Double" FontSize="12" Grid.Row="0" HorizontalContentAlignment="Center" Background="Aquamarine"/>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="3*"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button Name="IncomingConnection" Height="15" Width="15" Background="Black" Margin="5" VerticalAlignment="Top" HorizontalAlignment="Left"/>
<Button Name="OutgoingConnection" Grid.Column="2" Height="15" Width="15" VerticalAlignment="Top" Background="Black" Margin="5" HorizontalAlignment="Right"/>
<Button Name="OutgoingData" Grid.Column="2" Height="15" Width="15" VerticalAlignment="Bottom" Background="Aquamarine" Margin="5" HorizontalAlignment="Right"/>
</Grid>
</Grid>
</Border>
Anyways, I want to be able to click on one of these buttons (incomingConnection or outgoingConnection), and have a line connect the two buttons.
Other information: The custom controls are all being placed inside thumbs so they can be dragged around. Everything is on a canvas. I don't want to create a line between the controls, but instead between the buttons on the controls.
Thanks a ton!
I would have a class for the lines that contains the x and y coordinates for both endpoints. I would put an instance for each line in to a list on the view model. Then use an ItemsControl bound to that property with a Canvas as the template. You can then use a WPF Line control as the ItemTemplate for the ItemsControl. You can bind the Line control's X1, Y1, X2, and Y2 to the endpoint properties of the line class that was created at the beginning.
With that setup, all you have to do is add instances of your line class to the list and they will automatically show up on the Canvas.
I have a window with a TreeView with a BorderThickness of 1 and a StackPanel inside a Border element with a BorderThickness of 1.
As you can see in the following picture, the Border gets a shadowing effect but the Treeview doesn't. How to fix this (if possible remove the shadow effect)?
general view
zoom view
I tried setting BorderThickness of TreeView to 0 and put TreeView in a Border , but it didn't work.
XAML summary:
<Grid Name="MainGrid" Margin="5,5,5,5">
<Grid.RowDefinitions>
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions >
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="5" />
<ColumnDefinition Width="2*" />
</Grid.ColumnDefinitions>
<TreeView ItemsSource="{Binding FinalResult}"
SelectedItemChanged="TreeView_SelectedItemChanged"
BorderThickness="1"
>
<TreeView.Resources>
</TreeView.Resources>
</TreeView>
<GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Stretch" />
<Border BorderBrush="#ff828790" BorderThickness="1" Grid.Column="2">
<StackPanel>
</StackPanel>
</Border>
</Grid>
I think that you might benefit from using the UIElement.SnapsToDevicePixels Property. From the linked page:
Gets or sets a value that determines whether rendering for this element should use device-specific pixel settings during rendering.
If you set this property to true on your blurry control, it should align it directly with the actual pixels to remove the blurriness:
<Border BorderBrush="#ff828790" BorderThickness="1" Grid.Column="2"
SnapsToDevicePixels="True">
...
</Border>
Below is my xaml code :
<Window x:Class="ScoresBank.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow">
<DockPanel LastChildFill="True">
<WrapPanel DockPanel.Dock="Top">
<ToolBar Height="25"></ToolBar>
</WrapPanel>
<WrapPanel DockPanel.Dock="Bottom">
<StatusBar Name="stbBottom" Height="25"
BorderThickness="2"
BorderBrush="Black">Example</StatusBar>
</WrapPanel>
<StackPanel DockPanel.Dock="Left">
<DockPanel LastChildFill="True">
<WrapPanel DockPanel.Dock="Top">
<Button Name="btnBrowseTags">TAGS</Button>
<Button Name="btnBrowseTitles">TITLES</Button>
</WrapPanel>
<ComboBox DockPanel.Dock="Top" Name="cbxCategory">
Example
</ComboBox>
<WrapPanel DockPanel.Dock="Bottom">
<TextBox Name="txtKeyword"></TextBox>
<Button Name="btnFind">Find</Button>
</WrapPanel>
<ListBox Name="lbxBrowse">
</ListBox>
</DockPanel>
</StackPanel>
<StackPanel DockPanel.Dock="Right">
<Button>Example</Button>
</StackPanel>
<Canvas>
</Canvas>
</DockPanel>
And this is my current layout view :
So, what I mean with filling the container are :
Making lbxBrowse to fill the mid-space of the DockPanel inside the left StackPanel.
Making txtKeyword to fill the WrapPanel.
Making stbBottom to fill the WrapPanel.
What I've tried :
It seems i've put them in a DockPanel with LastChildFill="True". But it seems doesn't work.
I don't know about this, since it's not possible to put it into a DockPanel first.
I don't know anything about this.
I don't use fixed size, since I need them to keep neat even when resized in multiple screen resolution. The fixed size on ToolBar and StatusBar seems required, otherwise, the text will be unseen.
P.S. If possible, I prefer the solution to be XAML code, rather than the C# code. Otherwise, C# code is fine too.
Thank you.
You should use a Grid. It is more easier to configure. Here is an example (I don't know exactly how you want to setup your layout).
<Window x:Class="SampleWpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="400" Width="600">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Margin="5" Content="TAGS"
Grid.Column="0" Grid.Row="0" />
<Button Margin="5" Content="TITLES"
Grid.Column="1" Grid.Row="0" />
<Button Margin="5" Content="EXAMPLES"
Grid.Column="2" Grid.Row="0"
HorizontalAlignment="Right"/>
<ComboBox Margin="5"
Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1" />
<ListBox Margin="5"
Grid.Column="2" Grid.Row="1" Grid.RowSpan="2" />
<Button Margin="5" Content="EXAMPLE"
Grid.Column="2" Grid.Row="3" HorizontalAlignment="Left" />
</Grid>
</Window>
And the result:
With a grid you can set the height and the width of the columns and rows to a specific value (in points, pixels, cm, etc.), to column content (Auto) or proportional to the grid (with *).
Instead of using a StackPanel and DockPanel you can use Grid and set Grid.ColumnDefinitions and Grid.RowDefinitions. You can specify directly each row Height and each column Width. It's easier to use and it automaticly fit to content and container.
I have a DataTemplate for my WPF ListBox:
<DataTemplate DataType="{x:Type local:LogEntry}" x:Key="lineNumberTemplate">
<Grid IsSharedSizeScope="True">
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="Index" Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid Cursor="/LogViewer;component/Template/RightArrow.cur">
<Rectangle Fill="{Binding Path=LineNumbersBackgroundColor, ElementName=LogViewerProperty}" Opacity="0.4" />
<TextBlock Grid.Column="0" Margin="5,0,5,0" Style="{StaticResource MyLineNumberText}" x:Name="txtBoxLineNumbers" />
</Grid>
<TextBlock Grid.Column="1" Margin="5,0,0,0" Style="{StaticResource MyTextEditor}" />
</Grid>
</DataTemplate>
Is it possible that the selection box begins not at the beginning (MyLineNumberText) but at MyTextEditor? Sorry I don't know how to describe it in the right way.
Yes, it is possible. You have to modify the style of the listbox. If you are using Blend this is easy. Otherwise you could get the style for Listbox and ListboxIten here: http://msdn.microsoft.com/en-us/library/cc278062(v=vs.95).aspx
Copy the style to your project and then change the style acordingly.
I have a user control which contains a media element to play a video, a slider used as a trackbar for the video and a text block that display the title of the video. These 3 controls are placed in a grid which in turn is placed inside a border.
I want the user to be able to translate, rotate and scale this control. The problem is that when the control scales it's content scales also and i want the slider control not to scale. Is it possible to somehow keep the slider control from scaling?
I should also mention that the manipulation of the control is handled by setting the control ismanipulationenabled to true and using the manipulation delta event.
EDIT:
This is how the xaml for the control looks like:
<Grid Name="movieGrid" ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border x:Name="moviePlayerBorder" Background="Black" BorderBrush="Blue" BorderThickness="2,2,2,2" CornerRadius="5,5,5,5" Grid.RowSpan="2">
<Grid Name="contentGrid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<WinControls:MediaElement x:Name="movieDisplay" ScrubbingEnabled="True" IsEnabled="True" Grid.RowSpan="2"
LoadedBehavior="Manual" UnloadedBehavior="Manual"
MediaOpened="movieDisplay_MediaOpened">
</WinControls:MediaElement>
<Image x:Name="btnPlay" Grid.Row="1" Height="60" Width="60" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="120,44,112,43" Grid.RowSpan="2">
</Image>
<DockPanel LastChildFill="True" HorizontalAlignment="Stretch" Margin="6,2,6,0" Grid.Row="0">
<TextBlock Text="test" Margin="0,0,0,0" Name="txtBlockTitlu" HorizontalAlignment="Stretch"
FontSize="14" VerticalAlignment="Top" Foreground="White" TextWrapping="Wrap" Visibility="Collapsed"/>
</DockPanel>
</Grid>
</Border>
<Slider x:Name="seekBar" VerticalAlignment="Bottom" HorizontalAlignment="Center" Width="299"
Thumb.DragStarted="seekBar_DragStarted" Thumb.DragCompleted="seekBar_DragCompleted" Thumb.DragDelta="seekBar_DragDelta" MaxHeight="33"
Minimum="0" Maximum="286" Height="33" Margin="0,0,0,0" Grid.Row="1"/>
</Grid>
if you want to build a fully scaleable user control you should define the layout only with the size values of a row column / row row eg. auto, x* or fixed values (if realy needed).
do not use fixed size values on elements.