getting datagridrow of datagrid in WPF - wpf

I used this line in code but it does not give row object, row is null.
DataGridRow row =
(DataGridRow)dtgSensorReadingList.ItemContainerGenerator.ContainerFromItem(channelGrid.Items[i]);
Datagrid Xaml code:
<DataGrid Visibility="Hidden" VirtualizingStackPanel.VirtualizationMode="Standard"
CanUserAddRows="False" ColumnHeaderHeight="32" MinColumnWidth="65"
HorizontalGridLinesBrush="DarkKhaki" VerticalGridLinesBrush="DarkKhaki"
BorderBrush="DarkKhaki" Block.TextAlignment="Center" AutoGenerateColumns="True"
CanUserResizeColumns="False" CanUserReorderColumns="False" HorizontalAlignment="Left"
Margin="63,540,0,0" Name="dtgSensorReadingList" ItemsSource="{Binding}" Grid.Row="1"
Height="Auto" VerticalAlignment="Top" MaxWidth="1920" Width="Auto">
<DataGrid.Resources>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="Background" Value="SteelBlue" />
<Setter Property="Foreground" Value="white" />
<Setter Property="HorizontalContentAlignment" Value="Center"/>
</Style>
<Style TargetType="{x:Type DataGridRowHeader}">
<Setter Property="Background" Value="Transparent" />
</Style>
<Style x:Key="Body_Content_DataGrid_Centering" TargetType="{x:Type DataGridCell}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGrid.Resources>
</DataGrid>
Please let me know how can I get the DatGridRow ?

if you want the selected row you can bind to SelectedItem in your datagrid.
please tell us what you wanna achieve.

Related

I have ColumnHeaderStyle for Datagrid and Now i don't want to resize Columns

How can I resize datagrid'sColumns?
I have ColumnHeaderStyle for Datagrid and Now i don't can resize Columns!
Please help me!
i treid this code. but it does not work
CanUserResizeColumns="True"
<Style x:Key="ColumnHeaderStyle" TargetType="{x:Type DataGridColumnHeader}" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DataGridColumnHeader">
<StackPanel >
<DockPanel>
<Image DockPanel.Dock="Left" Source="/Images/Photo.png"/>
<TextBox Name="txtCaption" Text="{TemplateBinding Content}" />
</DockPanel>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<DataGrid Name="mainGrid" AutoGenerateColumns="False" IsReadOnly="True" AlternatingRowBackground="#FFEBEBFF"
ColumnHeaderStyle="{StaticResource ColumnHeaderStyle}">
</DataGrid>
In your case: you are using ColumnHeaderStyle so it restricts from resizing.
By default CanUserResizeColumns is true.
Instead of using ColumnHeaderStyle use below code:
<DataGridTextColumn Header="Header1" Width="auto" IsReadOnly="True" Binding="{myUserControls:CultureAwareBinding Path=xxxxx}">
<DataGridTextColumn.ElementStyle>
<Style TargetType="TextBlock">
<Setter Property="TextAlignment" Value="Right"></Setter>
</Style>
</DataGridTextColumn.ElementStyle>
<DataGridTextColumn.HeaderStyle>
<Style TargetType="DataGridColumnHeader">
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
</DataGridTextColumn.HeaderStyle>

WPF: How to use BasedOn Style

I am new to WPF and I created the following simple style example. But it doesn't work properly and button's content doesn't show although I can still click on it. Can anyone tell me why it is broken?
<Window.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border BorderBrush="Blue"
BorderThickness="5"
Background="Aqua"
Width="80"
Height="40">
<ContentPresenter></ContentPresenter>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="Grid" x:Name="GridWithMarginStyle">
<Setter Property="Margin" Value="12"></Setter>
</Style>
</Window.Resources>
<StackPanel>
<StackPanel.Resources>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
<EventSetter Event="Button.Click" Handler="ButtonHandler" />
<Setter Property="Background" Value="Red"></Setter>
<Setter Property="Foreground" Value="White"></Setter>
</Style>
</StackPanel.Resources>
<Button Name="OkBtn">OK</Button>
<Button Name="CancelBtn" Click="CancelBtn_Click">Cancel</Button>
</StackPanel>
You are using the BasedOn property in the correct way. The problem is that your ContentPresenter is not binded to the control it renders (i.e. the button).
Just try to replace your ControlTemplate XAML with this one:
<ControlTemplate TargetType="{x:Type Button}">
<Border BorderBrush="Blue"
BorderThickness="5"
Background="Aqua"
Width="80"
Height="40">
<ContentPresenter Content="{TemplateBinding Content}" />
</Border>
</ControlTemplate>
By using TemplateBinding you can bind the ContentPresenter to the Content property of your templated control.

How to center the content of cells in a data grid?

I set the min height of a datagrid that way:
<DataGrid MinRowHeight="40">
After feeding the datagrid with datas, the text in each cell is top and left aligned.
I could not find an easy way to center that text.
Any suggestions for doing that?
Final solution:
<Style x:Key="DataGridContentCellCentering" TargetType="{x:Type DataGridCell}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The following code will center the contents of cells in DataGrid:
<Style TargetType="DataGridCell">
<Setter Property="TextBlock.TextAlignment" Value="Center" />
</Style>
use ElementStyle
<DataGridTextColumn ElementStyle="{StaticResource Centering}"/>
<Style x:Key="Centering" TargetType="{x:Type TextBlock}">
<Setter Property="HorizontalAlignment" Value="Center" />
</Style>
you can use styles. i add a sample for DataGridCheckBoxColumn, i hope it put you in the right direction.
<DataGridCheckBoxColumn Header="is active" IsReadOnly="False">
<DataGridCheckBoxColumn.ElementStyle>
<Style TargetType="CheckBox">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
</Style>
</DataGridCheckBoxColumn.ElementStyle>
<DataGridCheckBoxColumn.Binding>
<Binding Path="ISACTIVE" ValidatesOnDataErrors="True" Converter="{StaticResource MyBoolToIsActiveConverter}" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged"
NotifyOnValidationError="True" ValidatesOnExceptions="True">
</Binding>
</DataGridCheckBoxColumn.Binding>
</DataGridCheckBoxColumn>
Try setting the DataGrid's Vertical and HorizontalContentAlignment to Center
<DataGrid VerticalContentAlignment="Center" HorizontalContentAlignment="Center" />
If that doesn't work, you can use the solution in this answer. It uses a style that aligns the DataGrid cell contents
This style will set the VerticalAlignment to Center for all DataGridCells without needing to be applied explicitly.
<Style TargetType="DataGridCell">
<Style.Resources>
<Style TargetType="ContentPresenter">
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
</Style.Resources>
</Style>
I find this to be the most elegant solution.
Modify your style tag like this.....
<Style x:Key="CellTextCentre" TargetType="DataGridCell">
<Setter Property="TextBlock.TextAlignment" Value="Center"></Setter>
<Setter Property="TextBlock.VerticalAlignment" Value="Center"></Setter>
</Style>
This below code display datagrid cell conent in center..
<Style x:Key="DataGridCellStyle" TargetType="DataGridCell">
<!--DISPLAY CONTENT IN MIDDLE-->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Here is a slightly longer version of Arpit Shah's answer.
<DataGrid AutoGenerateColumns="False" IsReadOnly="True" ItemsSource="{Binding Rows}">
<DataGrid.Resources>
<Style x:Key="RightAligned" TargetType="DataGridCell">
<Setter Property="HorizontalAlignment" Value="Right" />
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn CellStyle="{StaticResource RightAligned}"
Binding="{Binding Path=Quantity, Mode=OneWay}"
Header="Quantity" Width="60" />
<DataGridTextColumn Binding="{Binding Path=Category, Mode=OneWay}"
Header="Category" Width="150" />
</DataGrid.Columns>
</DataGrid>
Here a better approach to center the content vertically:
<Style TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource {x:Type DataGridCell}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

WPF ListView SelectionChanged inside style does not work. EventSetter either

<Style x:Key="OrderGroupTemplateStyle" TargetType="{x:Type ContentControl}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Name.ShowDetailedInfo, UpdateSourceTrigger=PropertyChanged}" Value="False">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Border BorderBrush="Gray" BorderThickness="2" CornerRadius="3" Margin="2">
<StackPanel Background="LightGoldenrodYellow">
<ContentControl Content="{Binding Path=.}" Style="{StaticResource MyRecordViewModelShortStyle}"/>
<ListView ItemsSource="{Binding Path=Items}" Margin="4">
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="HorizontalContentAlignment" Value="Stretch" /> <Setter Property="Padding" Value="2"/>
<EventSetter Event="MouseDoubleClick" Handler="ItemsControl_SelectionChanged"/>
</Style>
</ListView.ItemContainerStyle>
I would like to do some job when listview selection changed. because I am using style I cannot use SelectionChanged Event on ListView. I tried to use EventSetter but there is any error while compiling the project:
The event 'MouseDoubleClick' cannot be
specified on a Target tag in a Style.
Use an EventSetter instead.
Can someone please help me?
Try creating the Style as a resource instead of declaring it inline. I don't know why it behaves differently, but it appears to make the error go away:
<Style TargetType="{x:Type ListViewItem}" x:Key="ItemContainerStyle">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Padding" Value="2"/>
<EventSetter Event="MouseDoubleClick" Handler="ItemsControl_SelectionChanged"/>
</Style>
<Style x:Key="OrderGroupTemplateStyle" TargetType="{x:Type ContentControl}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Name.ShowDetailedInfo, UpdateSourceTrigger=PropertyChanged}" Value="False">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Border BorderBrush="Gray" BorderThickness="2" CornerRadius="3" Margin="2">
<StackPanel Background="LightGoldenrodYellow">
<ContentControl Content="{Binding Path=.}" Style="{StaticResource MyRecordViewModelShortStyle}"/>
<ListView ItemsSource="{Binding Path=Items}" Margin="4" ItemContainerStyle="{StaticResource ItemContainerStyle}"/>
I don't understand statement 'because I am using style I cannot use SelectionChanged Event on ListView'
But you can use SelectionChanged event of Listview, if you are using Style also.

WPF templating/styling issue

Given this piece of XAML
<DockPanel>
<DockPanel.Resources>
<Style TargetType="{x:Type GroupBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupBox}">
<DockPanel>
<Border DockPanel.Dock="Top">
<Border.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground"
Value="Red" />
</Style>
</Border.Resources>
<ContentPresenter ContentSource="Header" />
</Border>
<ContentPresenter />
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DockPanel.Resources>
<GroupBox VerticalAlignment="Top"
Header="GroupBox header"
DockPanel.Dock="Top">
...
...
I would like to know why the group box header is not displayed in red letters.
I've already tried styling the Label type with no success either.
(sorry about the overly generic post title... I wasn't able to think of something more meaninful)
This code solved the problem:
<DockPanel>
<DockPanel.Resources>
<Style TargetType="{x:Type GroupBox}">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<DataTemplate.Resources>
<Style TargetType="Label">
<Style.Setters>
<Setter Property="Foreground" Value="Red" />
</Style.Setters>
</Style>
</DataTemplate.Resources>
<Label Content="{Binding}" />
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</DockPanel.Resources>
<GroupBox VerticalAlignment="Top" Header="GroupBox header" DockPanel.Dock="Top">
...
...
However, I still don't know why the proposed code didn't worked.
It seems that the ContentPresenter doesn't use TextBlock to show the string you provide as header or explicitly sets its style, so the style you defined cannot be applied.
If you are certain that you will only use text as group box header, you can remove the ContentPresenter and use a TextBlock on your own.
<DockPanel>
<DockPanel.Resources>
<Style TargetType="{x:Type GroupBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupBox}">
<DockPanel>
<Border DockPanel.Dock="Top">
<Border.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Red" />
</Style>
</Border.Resources>
<TextBlock Text="{TemplateBinding Header}"></TextBlock>
</Border>
<ContentPresenter />
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DockPanel.Resources>
<GroupBox VerticalAlignment="Top"
Header="GroupBox header"
DockPanel.Dock="Top"/>
</DockPanel>
try this:
<DockPanel.Resources>
<Style TargetType="{x:Type GroupBox}" >
<Setter Property="Foreground" Value="Red" />
</Style>
</DockPanel.Resources>
You don't need a templet for this. But if you demand on using a Templete, you probably have to set the Groupbox.HeaderTemplet not the GroupBox.Templet.
Edit:
This is what i got so far, but i keep getting an XamlPraseException.
<Style TargetType="{x:Type GroupBox}" >
<Setter Property="HeaderTemplate">
<Setter.Value>
<ControlTemplate>
<StackPanel>
<StackPanel.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Red"/>
</Style>
</StackPanel.Resources>
<TextBlock Text="{TemplateBinding GroupBox.Header}" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Resources