XAML GridRow doesn't scale automatically when ErrorTemplate is displayed - c#

I have a XAML window with a TextBox, and this TextBox has an ErrorTemplate.
The ErrorTemplate is shown below, and as you can see, I have an AdornedElementPlaceholder, followed by a textbox whose Text field is bound to the ErrorContent:
<ControlTemplate x:Key="ValidationErrorTemplateTextBlock" TargetType="{x:Type Control}">
<Border BorderBrush="Red" BorderThickness="1">
<StackPanel Orientation="Vertical">
<AdornedElementPlaceholder Name="AdornedElementPlaceholder" />
<TextBlock Text="{Binding ElementName=AdornedElementPlaceholder, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}"
FontSize="10"
Background="Red"
Foreground="White"
Padding="2" />
</StackPanel>
</Border>
</ControlTemplate>
<TextBox IsEnabled="{Binding SendMessage}"
Text="{Binding AutoMessageSubject, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource StyleBase}"
Validation.ErrorTemplate="{StaticResource ValidationErrorTemplateTextBlock}"
HorizontalAlignment="Stretch"
Grid.Row="3"
Grid.Column="1"
Grid.ColumnSpan="2" />
This works fine, except for one thing: the TextBox is inside a GridRow, with a Height="Auto". The row scales itself based on the textbox, but when the ErrorTemplate appears, with an extra TextBox on the bottom - the GridRow doesn't scale up to contain the new TextBox, and the new TextBox overlaps the elements below it.
How can I solve this?

Validation.ErrorTemplate: Gets or sets the ControlTemplate used to generate validation error feedback on the adorner layer.
This means that if you use Validation.ErrorTemplate, the validation errors are displayed on the layer above usual content, so the "second" TextBlock is displayed over the grid, not within the grid cell.
I would implement INotifyDataErrorInfo instead of semi-obsolete IDataErrorInfo, use a custom textbox style, and bind the visibility of the second TextBlock to HasErrors property. The example below uses a ToolTip instead of the second TextBlock:
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip">
<Setter.Value>
<ToolTip DataContext="{Binding RelativeSource={RelativeSource Self}, Path=PlacementTarget}">
<ItemsControl DisplayMemberPath="ErrorContent" ItemsSource="{Binding Path=(Validation.Errors)}" />
</ToolTip>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>

You might want to try adding Row/Column Definitions:
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>

Related

ContentPresenter - HorizonalAlignment not working

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?

Resizeable multiple TextBoxes

I'm going to create some program that resizeable (with drag) multiple Textboxes.
But, I don't know how to build this layout. Is there know how to create drag layout?
It's not entirely clear what your exact specification is here. But the drawing makes it look like you want some cells within the grid to have grab handles for varying width, while others do not. For this purpose, you should be able to use the GridSplitter object.
For example:
<Window x:Class="TestSO36334781GridSplitter.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:p="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<Border BorderBrush="Black" BorderThickness="1">
<Grid>
<Grid.Resources>
<p:Style TargetType="GridSplitter">
<Setter Property="HorizontalAlignment" Value="Right"/>
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="Width" Value="5"/>
<Setter Property="Height" Value="10"/>
<Setter Property="Background" Value="Black"/>
<!-- Offset the splitter visually so it's centered over the gridline -->
<Setter Property="RenderTransform">
<Setter.Value>
<TranslateTransform X="2.5" Y="0"/>
</Setter.Value>
</Setter>
</p:Style>
<p:Style TargetType="TextBox">
<Setter Property="Height" Value="30"/>
</p:Style>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="Label1" Grid.Column="0"/>
<TextBlock Text="Label1" Grid.Column="1"/>
<TextBlock Text="Label1" Grid.Column="2"/>
<TextBox Grid.Row="1" Grid.Column="0"/>
<TextBox Grid.Row="1" Grid.Column="1"/>
<TextBox Grid.Row="1" Grid.Column="2"/>
<GridSplitter Grid.Row="1" Grid.Column="0"/>
<GridSplitter Grid.Row="1" Grid.Column="1"/>
<TextBox Grid.Row="2" Grid.ColumnSpan="3" Text="A wide textbox here"/>
</Grid>
</Border>
</StackPanel>
</Window>
The above shows a grid with three TextBox controls in the middle row, the widths of which can be modified by the user by dragging the GridSplitter between each of them. The labels above them (i.e. the TextBlock objects) are moved/resized as well, as they share the same column with each respective TextBox.
A fourth TextBox is shown, spanning three columns in the last row, to show how you can still have other grid elements independent of the splitters. I assume you can modify the basic idea to suit your specific needs.
Note that it's important you provide your specific formatting for the splitter objects, and that they appear after the controls they share grid elements with, so that they are above those controls in the z-order.
See also this Stack Overflow question: WPF user controlled grid column width
Addendum:
As hinted at in the (now deleted) comments by Joey, it is possible to place splitter controls without them having to share the cell with (and possibly obscuring) other elements in the grid. The following XAML snippet (i.e. just the Grid element) shows how that would work:
<Grid>
<Grid.Resources>
<p:Style TargetType="GridSplitter">
<Setter Property="HorizontalAlignment" Value="Right"/>
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="Width" Value="5"/>
<Setter Property="Height" Value="10"/>
<Setter Property="Background" Value="Black"/>
</p:Style>
<p:Style TargetType="TextBox">
<Setter Property="Height" Value="30"/>
</p:Style>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="Label1" Grid.Column="0"/>
<TextBlock Text="Label1" Grid.Column="2"/>
<TextBlock Text="Label1" Grid.Column="4"/>
<TextBox Grid.Row="1" Grid.Column="0"/>
<TextBox Grid.Row="1" Grid.Column="2"/>
<TextBox Grid.Row="1" Grid.Column="4"/>
<GridSplitter Grid.Row="1" Grid.Column="1" ResizeBehavior="PreviousAndNext"/>
<GridSplitter Grid.Row="1" Grid.Column="3" ResizeBehavior="PreviousAndNext"/>
<TextBox Grid.Row="2" Grid.ColumnSpan="5" Text="A wide textbox here"/>
</Grid>
The above eliminates the need for the RenderTransform, as each GridSplitter winds up centered in its own column. The ResizeBehavior is set to PreviousAndNext, so that dragging the splitter affects not the width of the column in which the splitter is contained, but instead the widths of the columns immediately before and after it.
It's possible that you could apply a DataGrid control in this scenario and get it to do what you want. But there's nothing in your question that suggests to me you need the full feature set of a DataGrid, or even that you'll be happy with some of the constraints that would involve (such as the way headings are formatted, and whether you can include other fixed-width elements in the layout).

Control template: how to create bindings

So, I have a datagrid that has different colour cells depending on the cell's value.
I also have a tooltip that displays some further information. This all works fine.
I, however, would like to alter the tooltip to show further information and also to be the same colour as the cell. So, I thought it would be wise to create a custom style for my tool tips. So, I have the below code.
<Style TargetType="ToolTip">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToolTip">
<Border CornerRadius="15,15,15,15"
BorderThickness="3,3,3,3"
Background="#AA000000"
BorderBrush="#99FFFFFF"
RenderTransformOrigin="0.5,0.5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="2*"/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0"/>
<TextBlock Grid.Row="1"/>
<TextBlock Grid.Row="2"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I have an object shown below that is bound to my datagrid. I want to bind the three properties to the three textboxes in my tooltip.
class MyTask
{
public string Name;
public int Code;
public string Description;
}
In my DataGrid I do the following to bind my data to my datagrid
ItemsSource="{Binding TaskList}"
Then in the DataGridTextColumn I bind to a property like below
DataGridTextColumn Header="Code" Binding="{Binding Code}"
This makes sense to me. I am however at a loss to see how I use binding when creating my custom tooltip. I read that I can use templatebinding. I still don't understand how my tooltip will bind to my object of type MyTask in my xaml above?
Update - hopefully make my question clearer
I want to know how to create the bindings in my control template (for the 3 textboxes) and then in the main part of my code how I bind to these text boxes. I then would like to know how to create a binding for the background colour of my control template, I believe this is something to do with relativesource?
When I'm reading other examples (changing the Template Property) I see lines like below. I don't really understand why you have to do it? Is it a case of if you didn't right the line below you wouldn't be able to create a binding on the Padding property?
<Border Padding="{Binding Padding}" ...>
You don't need TemplateBindng, as that is used for setting up the resulting template object to layout based on dynamically using the properties of the implementing control. See this CodePlex article for a good example of when you'd need such functionality.
You simply need to set the bindings of your TextBlock elements within your ToolTip. You don't really need a Template at all in this case, except that since you are using the same ToolTip across all your column cells, it will help you out as you don't need to copy-paste the same code three times. You are after something similar to this article, Tooltip in DataGrid in WPF.
A solution which would work specifically to your case would be like:
<DataGrid Name="TestGrid1" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Name">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}">
<TextBlock.ToolTip>
<ToolTip />
</TextBlock.ToolTip>
</TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Code">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Code}">
<TextBlock.ToolTip>
<ToolTip />
</TextBlock.ToolTip>
</TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Description">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Description}">
<TextBlock.ToolTip>
<ToolTip />
</TextBlock.ToolTip>
</TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
<DataGrid.Resources>
<Style TargetType="ToolTip">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToolTip">
<Border CornerRadius="15,15,15,15"
BorderThickness="3,3,3,3"
Background="#AA000000"
BorderBrush="#99FFFFFF"
RenderTransformOrigin="0.5,0.5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="2*"/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="{Binding Name}"/>
<TextBlock Grid.Row="1" Text="{Binding Code}"/>
<TextBlock Grid.Row="2" Text="{Binding Description}"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGrid.Resources>
</DataGrid>
You set the ToolTip property within the CellTemplate so that the resulting ToolTip that pops up has the same DataContext as the active row in the DataGrid. This way, you can simply do your property bindings as normal within your ToolTip ContentTemplate, since it has access to all the same properties as does your DataGrid for the row.
To use underlying DataGridCell Background as ToolTip Background, bind your Border Background as Background="{Binding PlacementTarget.Background, RelativeSource={RelativeSource AncestorType=ToolTip, Mode=FindAncestor}}" .
You are trying to show all the fields in the tooltip of a cell. That doesn't make sense. But still you can do that easily using
PlacementTarget property, which gives you the underlying Visual element. ContextMenu, Popup too expose this property.
PlacementTarget.DataContext will give you the underlying MyTask object.
PlacementTarget.Content will give you the content of the corresponding DataGridCell, in your case it will be TextBlock.
So, if you want to show 3 fields in your cell's tooltip, below code will work for you using point number 2 above.
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="Background" Value="Tomato"/>
<Setter Property="ToolTip">
<Setter.Value>
<ToolTip>
<ToolTip.Style>
<Style TargetType="ToolTip">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToolTip">
<Border CornerRadius="15,15,15,15"
BorderThickness="3,3,3,3"
Background="{Binding PlacementTarget.Background, RelativeSource={RelativeSource AncestorType=ToolTip, Mode=FindAncestor}}"
BorderBrush="#99FFFFFF"
RenderTransformOrigin="0.5,0.5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="2*"/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="{Binding PlacementTarget.DataContext.Name, RelativeSource={RelativeSource AncestorType=ToolTip, Mode=FindAncestor}}"
/>
<TextBlock Grid.Row="0" Text="{Binding PlacementTarget.DataContext.Code, RelativeSource={RelativeSource AncestorType=ToolTip, Mode=FindAncestor}}"
/>
<TextBlock Grid.Row="0" Text="{Binding PlacementTarget.DataContext.Description, RelativeSource={RelativeSource AncestorType=ToolTip, Mode=FindAncestor}}"
/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ToolTip.Style>
</ToolTip>
</Setter.Value>
</Setter>
</Style>
</DataGrid.CellStyle>
And, if you want to show only corresponding cell's field in your cell's tooltip, then remove the remaining 2 textblocks, and use only one as :
<TextBlock Text="{Binding PlacementTarget.Content.Text, RelativeSource={RelativeSource AncestorType=ToolTip, Mode=FindAncestor}}" />
If you want to show all 3 fields, then apply the ToolTip to DataGridRow using DataGrid.RowStyle. No change in code would be needed.
What about using a color property in MyTask?
class MyTask
{
public string Name { get; set; }
public int Code { get; set; }
public string Description { get; set; }
public SolidColorBrush Color { get; set; }
}
And binding to the color property:
<Style TargetType="ToolTip">
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="HasDropShadow" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToolTip">
<Border Name="Border" Background="{Binding Color}" BorderBrush="{StaticResource SolidBorderBrush}" BorderThickness="1" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}">
<StackPanel>
<TextBlock Text="{Binding Name}" />
<TextBlock Text="{Binding Code}" />
<TextBlock Text="{Binding Description}" />
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Why don't you go for DataTemplate of tool tip like give it's a key and apply it in your cell tool tip style.
<Style TargetType="ToolTip" x:Key="ToolTipStyle">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate TargetType="ToolTip">
<Border CornerRadius="15,15,15,15"
BorderThickness="3,3,3,3"
Background="#AA000000"
BorderBrush="#99FFFFFF"
RenderTransformOrigin="0.5,0.5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="2*"/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0"/>
<TextBlock Grid.Row="1"/>
<TextBlock Grid.Row="2"/>
</Grid>
</Border>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
Now, you can bind your property to textblock too.

ContentTemplate using C# instead of XAML in Windows Phone

What I am trying to do is use C# to write the code of ContentTemplate instead of XAML. Here is the XAML code that I have:
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="AnyButton">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="140"/>
<ColumnDefinition Width="310"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="/Images/AnyImage.png" Height="80" Width="80" HorizontalAlignment="Left" Margin="15,0,0,0"/>
<TextBlock Grid.Column="1" TextWrapping="Wrap" VerticalAlignment="Center" HorizontalAlignment="Left" Text="AnyText" FontSize="30" FontFamily="{StaticResource PhoneFontFamilySemiLight}" Margin="0,0,0,0"/>
</Grid>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
And here is the code that I used inside my ContentPanel to use the ContentTemplate:
<Button x:Name="MyButton"
Click="MyButton_Click"
ContentTemplate="{StaticResource AnyButton}"
Width="492" Height="130"
Margin="6,0,6,-6"
Background="#003d0a"/>
Now, my question is, is it possible to write the whole code using C#?
if you are trying to do it in styling purpose do it in the following way:
<Style x:Key="MyButton" TargetType="Button">
<Setter Property="Width" Value="460"></Setter>
<Setter Property="Background" Value="/Images/AnyImage.png"></Setter>
</Style>
define this in app.xaml or PhoneApplicationPage.resources and in your button control in xaml set your style to MyButton. for example:
<Button style={StaticResource MyButton}/>
if you also want to define width and height for your image you can do it same way by defining style in value section set the value with that style. for example:
<style x:key ="MyImage" TargetType="Image">
<setter property="Width" Value="150"/>
</style>
in my button style define background value ={StaticResource MyImage}

C# / WPF - DataGrid - Binding the Width of a TextBox in RowDetails to that of the containing DataGrid

My problem is similar to this one;
DataGrid RowDetails Width problem
Except I would like row details never to exceed the width of the columns it spans.
|--0--|--1--|--2--|--3--|--4--|
|---------Row-Details---------|
I have tried AreRowDetailsFrozen and this had no effect. I have also tried binding to the parent Grid's actual width (OneWay) but this causes the width to exceed that of my two screens.
Here is my current attempt (simplified);
<Grid>
<DataGrid x:Name="Grid"
Grid.Row="1"
ItemsSource="{Binding Collection}"
IsReadOnly="True"
AutoGenerateColumns="False"
ColumnWidth="Auto"
CanUserResizeColumns="False"
CanUserResizeRows="False"
RowDetailsVisibilityMode="VisibleWhenSelected"
AreRowDetailsFrozen="True"
SelectionUnit="FullRow"
VerticalAlignment="Top"
HorizontalAlignment="Center">
<DataGrid.RowDetailsTemplate>
<!-- Begin row details section. -->
<DataTemplate>
<TextBox DataContext="{Binding ErrorMessage}"
IsReadOnly="True"
Margin="5"
BorderBrush="Transparent"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.CanContentScroll="True"
TextWrapping="Wrap"
Text="{Binding .}">
</TextBox>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
</Grid>
This results in the following;
|--0--|--1--|--2--|--3--|--4--|
|---------Row-Details are as wide as the longest row in their content ---------|
Binding the width of the TextBox to any parent container (Grid, DataGrid, ItemsPresenter):
Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Grid}}, Path=ActualWidth, Mode=OneWay}"
Results in:
|------Viewable Area-------|
|---- Columns ----|
|---------Row-Details --------------------------------------------------------------|
It's very frustrating, I just want the Row Details not to change the width of the DataGrid, is that so much to ask? :)
The only way to accomplish this is to change DataGridRow ControlTemplate. There we can bind row details host width (DataGridDetailsPresenter) to width of cells. For example:
<Style x:Key="{x:Type dg:DataGridRow}" TargetType="{x:Type dg:DataGridRow}">
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" />
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="Validation.ErrorTemplate" Value="{x:Null}" />
<Setter Property="ValidationErrorTemplate">
<Setter.Value>
<ControlTemplate>
<TextBlock Margin="2,0,0,0" VerticalAlignment="Center" Foreground="Red" Text="!" />
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type dg:DataGridRow}">
<Border x:Name="DGR_Border"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="True">
<dgp:SelectiveScrollingGrid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<dgp:DataGridCellsPresenter x:Name="cellPresenter" Grid.Column="1"
ItemsPanel="{TemplateBinding ItemsPanel}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
<dgp:DataGridDetailsPresenter dgp:SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding RelativeSource={RelativeSource AncestorType={x:Type dg:DataGrid}}, Path=AreRowDetailsFrozen, Converter={x:Static dg:DataGrid.RowDetailsScrollingConverter}, ConverterParameter={x:Static dg:SelectiveScrollingOrientation.Vertical}}"
Grid.Column="1" Grid.Row="1"
Visibility="{TemplateBinding DetailsVisibility}" Width="{Binding ElementName=cellsPresenter, Path=ActualWidth}"/>
<dgp:DataGridRowHeader dgp:SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical" Grid.RowSpan="2"
Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type dg:DataGrid}}, Path=HeadersVisibility, Converter={x:Static dg:DataGrid.HeadersVisibilityConverter}, ConverterParameter={x:Static dg:DataGridHeadersVisibility.Row}}"/>
</dgp:SelectiveScrollingGrid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Hope this helps.
I answered a similar question here DataGrid RowDetails Width problem
The answers here felt like a workaround so I did some research and did
find the solution on the Telerik forums, since we use their
RadGridView. Turned out the solution worked for DataGrid as well.
The key is to set the ScrollViewer.HorizontalScrollBarVisibility
property to Disabled, see example below.
<DataGrid ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<Border>
<TextBlock Foreground="White" Text="{Binding RowDetails}"
TextWrapping="Wrap"/>
</Border>
</DataTemplate>
</DataGrid.RowDetailsTemplate> </DataGrid>
I've found another way to fix the Problem:
private void GridOnLoadingRowDetails(object sender, DataGridRowDetailsEventArgs e)
{
var dataGridColumnHeadersPresenter = FindVisualChild<DataGridColumnHeadersPresenter>((DataGrid)sender);
e.DetailsElement.SetBinding(WidthProperty, new Binding("ActualWidth") { Source = dataGridColumnHeadersPresenter });
}
This prevents you from using constant values (e.g. '6') - which won't fit, if someone set DataGrid.RowHeaderWidth - and Converters.
I've added this to the DataGrid.LoadingRowDetails event handler, since I am already tweaking the RowDetails in some other ways.

Categories