How can I get a handle for the GridSplitter inside the TitleTemplate of RadPane
<telerik:RadPane TitleTemplate="{StaticResource radPaneHeaderFormat}" ContextMenuTemplate="{x:Null}" CanDockInDocumentHost="False" x:Name="radPane" Header="HeaderTitle" CanUserClose="False" CanFloat="False" VerticalAlignment="Center" />
<DataTemplate x:Key="radPaneHeaderFormat}" ">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="670" MaxWidth="678"/>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="0.1*" />
</Grid.ColumnDefinitions>
<Button x:Name="ViewButton" Margin="0,0,5,0" Style="{StaticResource LeftArrowButtonStyle}" Click="ViewButton_Click" />
<TextBlock Text="Summary" VerticalAlignment="Center" Grid.Column="1" />
<sdk:GridSplitter Height="Auto" Grid.Column="2" Name="HeaderSplitter" VerticalAlignment="Stretch" Style="{StaticResource newGridSplitterStyle}" />
<TextBlock Text="Note" Grid.Column="3" VerticalAlignment="Center" Margin="3,0,0,0"/>
</Grid>
</DataTemplate>
Can any one help me with this issue.
I don't know from where you want to access the GridSplitter, but, given that you have a Button with a Click event handler, I'll show you how you can access it in there:
private void ViewButton_Click(object sender, RoutedEventArgs e)
{
var button = sender as Button;
var panel = button.Parent as Panel;
if (panel != null)
{
GridSplitter splitter = panel.Children.OfType<GridSplitter>().First();
// do stuff with the GridSplitter...
}
}
You will need to add a line using System.Linq; if you don't already have one.
In this case I'm making use of the fact that the button's Click event handler passes us the button that was clicked, and that the Button and the GridSplitter have the same parent.
Related
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="0.55*" />
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Background="Gray">
<TextBlock x:Name="EmployeeNameTextBlock"
VerticalAlignment="Center"
Margin="50,0,0,0"
FontSize="18"
RenderTransformOrigin="0.5,0.5"
Text="Content09asdfadsdsdasdfasd92168132 "
TextWrapping="NoWrap"
/>
<ToggleButton x:Name="btn"
HorizontalAlignment="Left"
Margin="0,0,0,0"
VerticalAlignment="Center"
Height="30"
Width="30" >
Button
</ToggleButton>
</StackPanel>
<Label Grid.Column="1" Background="Yellow" />
</Grid>
This is my code i have issue in displaying the toggle button, you can refer to screen shot below for currently displaying and expectation
conditions
* button should be always end of the text block even content is small or big
* if content is bigger then container, textbox size should stop at before less width of button. so that we can see toggle button on display. as shown in expected screen shot.
Result Screenshot long text
Result Screenshot small text
Expected screenshot long text
Expected Screenshot small text
Please any one help on this
Thanks in advance
Solution
<Grid SizeChanged="Grid_SizeChanged">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="0.55*" />
</Grid.ColumnDefinitions>
<Border Name="rightBlk" Background="Green" Grid.Column="1" />
<Grid VerticalAlignment="Center" Background="Gray">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock x:Name="EmployeeNameTextBlock"
VerticalAlignment="Center"
Margin="50,0,0,0"
TextTrimming="CharacterEllipsis"
FontSize="18"
RenderTransformOrigin="0.5,0.5"
Text="Content09asasdfasdfd "
TextWrapping="NoWrap"
Padding="0,0,30,0"
/>
<ToggleButton x:Name="btn"
HorizontalAlignment="Right"
Margin="0,0,0,0"
VerticalAlignment="Center"
Height="30"
Width="30" >
Button
</ToggleButton>
</Grid>
<Label Grid.Column="1" Background="Yellow" />
</Grid>
Code Behide
private void Grid_SizeChanged(object sender, SizeChangedEventArgs e)
{
EmployeeNameTextBlock.MaxWidth = ((Grid)sender).ActualWidth - 50 - rightBlk.ActualWidth;
}
Thank you #lvan and #Neptune for helping me to solve this issue.
You can replace the StackPanel with a Grid. This way you have more control on distribution and can give your Button priority to get its width first before allocating the remaining to the TextBlock:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="0.55*" />
</Grid.ColumnDefinitions>
<Grid VerticalAlignment="Center" Background="Gray">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock x:Name="EmployeeNameTextBlock"
VerticalAlignment="Center"
Margin="50,0,0,0"
TextTrimming="CharacterEllipsis"
FontSize="18"
RenderTransformOrigin="0.5,0.5"
Text="Content09asdfadsdsdasdfasd92168132 "
TextWrapping="NoWrap"
/>
<ToggleButton x:Name="btn" Grid.Column="1"
HorizontalAlignment="Left"
Margin="0,0,0,0"
VerticalAlignment="Center"
Height="30"
Width="30" >
Button
</ToggleButton>
</Grid>
<Label Grid.Column="1" Background="Yellow" />
</Grid>
I added an attribute TextTrimming if you want to indicate to user there's missing text but you can remove it if that's not needed.
The code above produces this result when the width is limited:
You can get what you are looking for with either you code and adding
MaxWidth="270" and TextTrimming="CharacterEllipsis" to textbox
or Neptunes code and changing
<ColumnDefinition Width="*" /> to "Auto" and also adding MaxWidth="270" to textbox.
I don't think you can do it without setting a MaxWidth on the textbox but that means you'll have to recalculate it if you resize your window.
To recalculate:
Subscribe to main window size changed event:
SizeChanged += MainWindow_SizeChanged; within main window constructor or in xaml
And add to codebehind:
private void MainWindow_SizeChanged(object sender, SizeChangedEventArgs e)
{
EmployeeNameTextBlock.MaxWidth = StackPanelName.ActualWidth - btn.ActualWidth;
}
You might need to use .Width instead of Actual width, and you can also try using the column instead of the stack panel but this illustrates the recalculation you need to do.
I have a ListBox that contains a TextBox (And also picture and other thing).
The problem is I can't left click in the TextBox because of the previewmouseleftbuttondown which i handle for the ListBox.
It means that the program handle my left click with this function and thats why I can't write in the textBox.
What can i do about it?
The listBox:
ListBox x:Name="lbTwo" Grid.Column="2 " Margin="{StaticResource SplitRight}"
Drop="ListBox_Drop" AllowDrop="True"
PreviewMouseLeftButtonDown="ListBox_PreviewMouseLeftButtonDown" MouseDown="someListBox_MouseDown"
Style="{DynamicResource ResourceKey=styleLightListBox}"
ScrollViewer.VerticalScrollBarVisibility="Visible">
The items it contains:
<DataTemplate x:Key="templateLightListBoxItem">
<Grid Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Border Grid.Column="0"
Grid.Row="0"
Grid.RowSpan="2"
Margin="0,0,10,0">
<Image Source="{Binding Path=Number_pic}"
Stretch="Fill"
Height="40"
Width="40"></Image>
</Border>
<TextBlock Text="{Binding Path=Name}"
FontWeight="Bold"
Grid.Column="1"
Grid.Row="0"></TextBlock>
<Grid
Grid.Column="1"
Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label x:Name="label" Content="Your number: " Grid.Column="0" />
<TextBox x:Name="NumberTextBox" PreviewTextInput="NumberValidationTextBox" Text="{Binding Path=mainNumber, UpdateSourceTrigger=PropertyChanged}" Grid.Column="1" Width="20"/>
</Grid>
</Grid>
</DataTemplate>
Edit:
private void ListBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
ListBox destLisBox = (ListBox)sender;
dragSource = destLisBox;
GiveFeedbackEventHandler handler = new GiveFeedbackEventHandler(DragSource_GiveFeedback);
this.dragSource.GiveFeedback += handler;
object data = GetDataFromListBox(dragSource, e.GetPosition(destLisBox));
if (data != null)
{
DragDrop.DoDragDrop(destLisBox, data, DragDropEffects.Move);
}
}
private void DragSource_GiveFeedback(object sender, GiveFeedbackEventArgs e)
{
try
{
//This loads the cursor from a stream ..
if (_allOpsCursor == null)
{
{
_allOpsCursor = new Cursor(path+#"\Icons\Red_Gear.cur");
}
}
Mouse.SetCursor(_allOpsCursor);
e.UseDefaultCursors = false;
e.Handled = true;
}
finally { }
}
I am currently fighting against another WPF struggle, namely mouse events.
I basically have a very simple control (a Border containing a Grid which itself has a few TextBlocks). I am trying to achieve a simple behavior: Double click should turn the control into edit mode (which in fact hides the TextBlocks with TextBoxes bound to the same data.
Nothing fancy, right? Well still, I'm struggling. The MouseDoubleClick linked to my UserControl just fires when I click in a control (like, clicking ON a TextBlock). If I click on an empty space between TextBlocks, nothing is fired. Not even MouseDown.
How could I make it work so as to catch every mouse click? I assumed that linking a MouseDown event to a Border should catch every click on the border but... it ended up not catching clicks on empty parts of the border.
Here is some draft code I made for you to run it:
XAML:
<StackPanel Orientation="Vertical">
<Border Height="400" Width="400" HorizontalAlignment="Center" VerticalAlignment="Center" BorderBrush="Black" BorderThickness="2"
MouseDown="Border_MouseDown" MouseUp="Border_mouseUp">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Text="BLUFF" Grid.Column="0" Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Text="BLUFF" Grid.Column="0" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Text="BLUFF" Grid.Column="0" Grid.Row="2" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Text="BLUFF" Grid.Column="1" Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Text="BLUFF" Grid.Column="1" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Text="BLUFF" Grid.Column="1" Grid.Row="2" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Text="BLUFF" Grid.Column="2" Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Text="BLUFF" Grid.Column="2" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock Text="BLUFF" Grid.Column="2" Grid.Row="2" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Border>
<TextBlock Height="100" Width="300" HorizontalAlignment="Center" TextAlignment="Center" x:Name="thetext" Visibility="Collapsed"
Foreground="White" Background="Red" Text="CLICKED!" />
</StackPanel>
Code behind:
private void Border_MouseDown(object sender, MouseButtonEventArgs e)
{
thetext.Visibility = Visibility.Visible;
}
private void Border_mouseUp(object sender, MouseButtonEventArgs e)
{
thetext.Visibility = Visibility.Collapsed;
}
Now try to click one of the "BLUFF" texts: A "CLICKED" Text will appear. Try clicking somewhere else, between the TextBlocks: Nothing happens.
Thank you!
<StackPanel Background="Transparent" ... >
or
<Border Background="Transparent" ... >
should do the trick...
This makes the grid transparent, however visible for mouse-clicks.
Look here form more Information.
There are some other circumstances, where you have to use the PreviewXXX- event, this is when a child element "swallows" the event away, but in your case, the above should be what you're looking for.
With the XAML below when I drag the GridSplitter to the left it pushes elements out of the window.
How can I keep all elements within the window frame?
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Content="0" />
<Button Grid.Column="1" Content="1" />
<Button Grid.Column="2" Content="2" />
<GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Left" />
</Grid>
Thanks
The only way I know to solve your problem is have the columns that are left and right of your gridsplitter have the width property set as Width="*" and give the GridSplitter its own column with a HorizontalAlignment set as HorizontalAlignment="Stretch". Your code would then end up looking like this.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Content="0" />
<GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Stretch"/>
<Button Grid.Column="2" Content="1" />
<Button Grid.Column="3" Content="2" />
</Grid>
I was having this same issue, and came up with this solution. Basically, the idea is to dynamically change the MaxWidth of the appropriate column when the grid/columns change. I've shown with two columns here, but I've used this approach with three columns successfully.
With this approach, if you resize the window down to not fit the contents of the grid anymore, the grid stops changing size, so the ResizeGrid_SizeChanged event stops getting called. To solve for this, you can also listen for the window (or user control) size change events. You may also need to bind the MaxWidth of your grid appropriately, or use the control size directly if your grid fills the window/UserControl. I've shown how to bind the MaxWidth property through XAML here. If you didn't want to do that, you could replace "ResizeGrid.MaxWidth" with "ActualWidth" inside the window code behind, and remove the "MaxWidth" binding on the "ResizeGrid" object.
XAML:
<Window x:Class="App.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:Default="clr-namespace:App"
mc:Ignorable="d"
SizeChanged="Window_SizeChanged"
Title="Window1" Height="300" Width="300">
<Grid>
<Grid x:Name="ResizeGrid" SizeChanged="ResizeGrid_SizeChanged"
MaxWidth="{Binding ActualWidth, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Default:Window1}}}">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="C0" Width="150" MinWidth="50" />
<ColumnDefinition Width="5" />
<ColumnDefinition x:Name="C2" Width="*" MinWidth="50" />
</Grid.ColumnDefinitions>
<Grid Grid.Column="0" Background="Green">
<Label Content="Left" />
<Label Content="Right" HorizontalAlignment="Right" />
</Grid>
<GridSplitter Grid.Column="1" Width="5" HorizontalAlignment="Stretch" DragCompleted="GridSplitter_DragCompleted" />
<Grid Grid.Column="2" Background="Red">
<Label Content="Left" />
<Label Content="Right" HorizontalAlignment="Right" />
</Grid>
</Grid>
</Grid>
</Window>
C# Code Behind
private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
{
UpdateGridSplitterWidths();
}
private void ResizeGrid_SizeChanged(object sender, SizeChangedEventArgs e)
{
UpdateGridSplitterWidths();
}
private void GridSplitter_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e)
{
UpdateGridSplitterWidths();
}
private void UpdateGridSplitterWidths()
{
C0.MaxWidth = Math.Min(ResizeGrid.ActualWidth, ResizeGrid.MaxWidth) - (C2.MinWidth + 5);
}
Just to add to #Joseph's answer, which pointed me in the right direction, it still works when you fraction the "*", or include min/max widths.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.35*"
MinWidth="48" />
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"
MaxWidth="48" />
</Grid.ColumnDefinitions>
This lets you set the initial width of each column in keeping with your intent, as well as providing the functionality of not pushing things off screen.
I create a GridSplitter across the 3 rows that I have in my grid like this:
<GridSplitter Grid.Row="0" Grid.Column="1" Background="Yellow"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Width="Auto" Height="Auto" ResizeDirection="Columns"
Grid.RowSpan="3" ...
However, it's conceivable that I might add another row to my grid at a later stage, and I don't really want to go back and update all of my rowspans.
My first guess was Grid.RowSpan="*", but that doesn't compile.
A simple solution:
<!-- RowSpan == Int32.MaxValue -->
<GridSplitter Grid.Row="0"
Grid.Column="1"
Grid.RowSpan="2147483647" />
You can bind to the RowDefinitions.Count but would need to update the binding when adding rows manually.
Edit: Only semi-manually in fact
Xaml:
<StackPanel Orientation="Vertical">
<Grid Name="GridThing">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.Children>
<Button Content="TopRight" Grid.Row="0" Grid.Column="1"/>
<Button Content="LowerRight" Grid.Row="1" Grid.Column="1"/>
<Button Content="Span Rows" Name="BSpan" Grid.RowSpan="{Binding RelativeSource={RelativeSource AncestorType=Grid}, Path=RowDefinitions.Count, Mode=OneWay}"/>
</Grid.Children>
</Grid>
<Button Click="Button_Click" Content="Add Row" />
</StackPanel>
Code:
private void Button_Click(object sender, RoutedEventArgs e)
{
GridThing.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(20) });
foreach (FrameworkElement child in GridThing.Children)
{
BindingExpression exp = child.GetBindingExpression(Grid.RowSpanProperty);
if (exp != null)
{
exp.UpdateTarget();
}
}
}
The Grid control provides nothing like this out of the box. It's conceivable that you could implement a MarkupExtension or some other trickery to enable this.