I have a problem with my Datagrid. (MVVM)
I have a textbox that sets the SelectedIndex depending on where I click in the text. This works!
But the table in the datagrid can get quite long, and if the line that I want to highlight is not visible when clicking in the textbox it does not mark the line as selected.
So my question is if it is possible to select the line even though it is not visible? So if i scroll down that it shows the line as selected.
Or what would probably be better just jump to this line if not visible. (Set to top row or scroll to it automatically). Is this possible, if yes how?
Here is the xaml of the datagrid :
<DataGrid Name="dtgDecodedMsg"
CanUserSortColumns="False"
CanUserAddRows="False"
CanUserReorderColumns="False"
HeadersVisibility="Column"
IsTabStop="False"
ClipboardCopyMode="IncludeHeader"
SelectedIndex="{Binding DecodeSelectedGridIdx, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
ItemsSource="{Binding Path=MsgTypGridLineListVar, UpdateSourceTrigger=PropertyChanged}"
AutoGenerateColumns="False"
Margin="10,111,10,0">
This is how I highlight the Rows : (The rows don't get highlighted even if I set index on DecodeSelectedGridIdx and call the OnPropertychanged)
<DataGridCheckBoxColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="BorderBrush" Value="Aqua"/>
<Setter Property="BorderThickness" Value="2"/>
</Trigger>
</Style.Triggers>
This is how I set the index :
public int DecodeSelectedGridIdx
{
set
{
this.m_decodeSelectedGridIdx = value;
...
OnPropertyChanged("DecodeSelectedGridIdx");
}
}
Thank you for your help !
You could handle the SelectionChanged event for the DataGrid in the view and call the ScrollIntoView method:
private void dtgDecodedMsg_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
dtgDecodedMsg.ScrollIntoView(dtgDecodedMsg.SelectedItem);
}
XAML:
<DataGrid Name="dtgDecodedMsg" ... SelectionChanged="dtgDecodedMsg_SelectionChanged">
...
You could wrap this functionality in a behaviour if you intend to use it in several views: https://www.codeproject.com/Articles/28959/Introduction-to-Attached-Behaviors-in-WPF
Related
I have the following XAML in my view:
<tg:RadDataGrid ColumnDataOperationsMode="Flyout" x:Name="grid3" ItemsSource="{x:Bind ViewModel.MappingSource}" SelectedItem="{x:Bind ViewModel.CurrentMapping, Mode=TwoWay}" UserEditMode="{x:Bind ViewModel.CanEdit, Mode=TwoWay}" Grid.ColumnSpan="4" Grid.Row="1" AutoGenerateColumns="False" RowBackground="{x:Bind ViewModel.ValidateModBank}">
Please take a look at the end of the line where it sets the RowBackground property. At this time my ValidateModBank property returns the color red based on certain criteria.
The problem is that all the rows in the RadDataGrid get changed to red, but I only want specific rows to change - based on ValidateModBank.
How can I achieve this?
The RowBackground property is used to sets the Brush that defines the fill of each row, it's not for a specific row.
According to your description, you might want to change background of the selected row.
You could use its Implicit Styling.
Setting the SelectionRegionBackground Control for it.
<telerikGrid:RadDataGrid.Resources>
<Style TargetType="gridPrimitives:SelectionRegionBackgroundControl">
<Setter Property="Background" Value="Red"/>
<Setter Property="BorderBrush" Value="Green"/>
<Setter Property="BorderThickness" Value="2"/>
</Style>
</telerikGrid:RadDataGrid.Resources>
I have a Datagrid containing items as List, one property in this custom list is a bool which determines visibility (the visibility can be toggled by a checkbox).
I have that working as this:
<Style x:Key="RowStyle" TargetType="DataGridRow">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsVisible}" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=IsVisible}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
And my Datagrid is like:
<DataGrid Name="dataList" DataContext="{StaticResource DataViewSource}" ItemsSource="{Binding}"
ItemContainerStyle="{StaticResource RowStyle}"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
AutoGenerateColumns="False"
CanUserAddRows="False"
CanUserDeleteRows="False"
IsReadOnly="True"
CanUserReorderColumns="True" CanUserSortColumns="True"> ..etc
Assume I have 100 rows and when toggling the visibility, 80 of those rows are collapsed.
The issue is: the scrollbar doesn't seem to update when the visibility of items is changed. In appearance it will look as if those 80 rows are still visible (small drag bar) but when trying to scroll through the 20 items that are visible, it requires a lot more scrolling because the scrollbar is assuming that it's still having to scroll through 100 items or something.
Is there a way I can inform the scrollbar of visibility changes? Or should I handle the scroll event myself and remove the scrollbar from the datagrid?
The Datagrid uses something called row virtualization by default. When row virtualization is enabled, the scrollbar uses logical scoll units (items) instead of the real size.
Because your collection still contains all items, the scrollbar size does not change.
Solution:
Use the Filter event of the CollectionViewSource instead of binding to the Items viewmodel. MSDN
I have a WPF app and I want to add an item with HorizontalAlignment = Left and then other with HorizontalAlignment = right, like a chat in Whatsapp, but all the text in the listbox have horizontal alignment on the right, How can I use different horizontal alignment in the same listbox.
This is my XAML code:
<ListBox x:Name="ListBoxChat" HorizontalAlignment="Stretch" Height="366" VerticalAlignment="Top" Width="270" Margin="2,44,0,0" Padding="2"/>
<TextBlock Foreground="Transparent" Name="TextB" Margin="2,-5,2,-3"></TextBlock>
and this is the C# code behind:
ListBoxChat.HorizontalAlignment = HorizontalAlignment.Left;
ListBoxChat.Items.Add("How are you ?");
ListBoxChat.HorizontalAlignment = HorizontalAlignment.Right;
ListBoxChat.Items.Add("Fine!!!");
Thank you!
You can create a single StackPanel to carry the ListView. Like this,
<StackPanel>
<ListView x:Name="chatList" Width="value" />
</StackPanel>
You don't really need the StackPanel, I just used it!
Now on the CSharp code, you can handle the events of the User or the Network. I won't go in the Depth of the process, but an example of that would be
void addItem (object sender, EventArgs e) {
// first create the new item!
ListViewItem item = new ListViewItem();
// add the properties..
item.Content = "Hi, my name is Slim Shady!";
if(messageBy == "user") {
// if message is by user, align it to right
item.HorizontalAlignment = HorizontalAlignment.Left;
} else {
// if message is by network (friend), align it to left
item.HorizontalAlignment = HorizontalAlignment.Right;
}
// now add the item to the listbox
chatList.Items.Add(item); // done! :-)
}
You can execute this code, each time there is new item to be appened! But you really need to make sure that the conditions are checked. Because using the Condition, you can change the color of the item too, like in WhatsApp, you can do other stuff too. It totally depends on the Condition, and the Way you use it.
Good luck!
You can achieve this by applying the style on your ListBoxItem and using AlternationCount and AlternationIndex as shown below:
<ListBox x:Name="ListBoxChat" HorizontalAlignment="Stretch" Height="366" VerticalAlignment="Top" Width="270" Margin="2,44,0,0" Padding="2"
AlternationCount="2">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=(ItemsControl.AlternationIndex),
RelativeSource={RelativeSource Self}}" Value="0">
<Setter Property="HorizontalContentAlignment" Value="Left"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Path=(ItemsControl.AlternationIndex),
RelativeSource={RelativeSource Self}}" Value="1">
<Setter Property="HorizontalContentAlignment" Value="Right"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
I'm currently building up a WPF Window holding a table using the DataGrid. Binding and updates work fine, I'm also quite contempt with the styling, but I ran into troubles when it comes to selection. This are the prerequisites:
Table is ReadOnly
Whole Row Selection
This is the source code for my table: (Yes, I know I did set the selection color 3 times, once for DataGrid, once for the row, once for the cell. I thought maybe one of those would be helping, but it's not the case.)
<DataGrid x:Name="dgv" SelectionMode="Single" SelectionUnit="FullRow" AutoGenerateColumns="False" Grid.Column="0" Grid.RowSpan="3" Margin="8" RowHeight="32" GridLinesVisibility="Horizontal" HeadersVisibility="Column" HorizontalScrollBarVisibility="Hidden"
CanUserAddRows="False"
CanUserDeleteRows="False"
CanUserReorderColumns="False"
CanUserResizeColumns="False"
CanUserResizeRows="False"
CanUserSortColumns="True"
IsReadOnly="True"
LoadingRow="dgv_LoadingRow"
>
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Red"></SolidColorBrush>
</Style.Resources>
<Setter Property="VerticalAlignment" Value="center"></Setter>
<Setter Property="Padding" Value="4"></Setter>
<Setter Property="Margin" Value="4"></Setter>
</Style>
</DataGrid.CellStyle>
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Red"></SolidColorBrush>
</Style.Resources>
</Style>
</DataGrid.RowStyle>
<DataGrid.Style>
<Style TargetType="DataGrid">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Red"></SolidColorBrush>
</Style.Resources>
</Style>
</DataGrid.Style>
It then continues to Column- and RowDefinitions ...
I run into the following problems:
Only the cells get selected, not the whole line. The margins in the Cells make it look quite weird (See Screenshot)
The row doesn't select when I click on a margin of a cell (the areas in the Screenshot that are not rendered in red) - makes selecting rows quite unintuitive...
The cell that I click on to select the row still gets hihglighted (notice the black border around "Peter Müller" in the selected row)
Here's a screenshot of the outcome:
What if you were to remove the margin in the cell definition? That is accounting for the cells taking up extra space and the red not covering that space. If you removed the margin, do you get what you are looking for. I think the real answer may be in the DataGrid.RowBackground [Property][1].
Property Value
Type: System.Windows.Media.Brush
The brush that paints the background of a row. The registered default is null. For more information about what can influence the value, see DependencyProperty.
You could use a trigger on the IsSelected state to set the color. By default the entire row of a DataGrid is selected.
<DataGrid Name="dataGrid1" Margin="12,12,0,0">
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Setter Property="Background" Value="LightBlue" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
</DataGrid>
Inorder to change default background row selection. you need to
1) edit datagridrow style & template (i.e http://msdn.microsoft.com/en-us/library/cc278066%28v=vs.95%29.aspx)
2) handle selectionchanged event and changed background of row.
3) or on datagrid row loaded event get the childrenoftype rectangle equal to "BackgroundRectangle" and set color you want - so using this it effects to all the rows in a datagrid, it is similar to 1 but doing this in code behind.
hope this gives you some idea.
I have a DataGrid that is setup like this:
<DataGrid
AutoGenerateColumns="True"
GridLinesVisibility="Horizontal"
IsReadOnly="True"
ItemsSource="{Binding Documents}"
SelectionMode="Single"
SelectionUnit="FullRow"
/>
Can somebody point me in the right direction for making the UI look as though the entire row is selected, by not highlighting the cell that is clicked?
You will want to expermient with cell styles. I think the default cell style checks for IsSelected and if it is the border will be colored with a black brush.
Because you are using AutoGenerateColumns, then you probably need to set the styles for the columns once they have been generated in the code behind.
I'm guessing that if you create a style, check for IsSelected and set the borderbrush to transparent, set the style for the datagrid's columns (ElementStyle + ElementEditingStyle) then you should be set. I'm writing this from the top of my head, but that's the general direction I think.
Thanks Marko for pointing me in the right direction. Here is how I changed my datagrid to make it not look like any cell was selected. Instead now it appears that the whole row is seleted. I chose to set the border's background to the current cells background so that I also didn't have to set the border thickness.
<DataGrid ...>
<DataGrid.CellStyle>
<Style TargetType="DataGridCell" >
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter
Property="BorderBrush"
Value="{Binding RelativeSource={RelativeSource Self}, Path=Background}"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.CellStyle>
</DataGrid>