I have tried to bind a List of objects to a ListBox, but when run it has no items in the ListBox, the List itself does have items.
List<Module> _modules
public class Module
{
public Module(string ModuleName, string ModuleAbbreviation, string ModuleColor, bool ModuleAvailable)
{
this.ModuleName = ModuleName;
this.ModuleAbbreviation = ModuleAbbreviation;
this.ModuleColor = ModuleColor;
this.ModuleAvailable = ModuleAvailable;
}
public string ModuleName { get; set; }
public string ModuleAbbreviation { get; set; }
public string ModuleColor { get; set; }
public bool ModuleAvailable { get; set; }
}
ViewModel code is below (it has been shortened, the relevant code for the Module List has been included):
namespace Users.ViewModel
{
public class AllUsersViewModel
{
public List<Module> _modules = new List<Module>();
#region Constructor
public AllUsersViewModel()
{
this.SetModuleList();
this.CreateAllUsers();
}
void SetModuleList()
{
_modules = ModuleRepository.GetModules();
}
public IEnumerable<Module> Modules
{
get { return _modules; }
}
void CreateAllUsers()
{
List<UserViewModel> all =
(from cust in _userRepository.GetUsers()
select new UserViewModel(cust, _userRepository)).ToList();
foreach (UserViewModel cvm in all)
cvm.PropertyChanged += this.OnUserViewModelPropertyChanged;
this.AllUsers = new ObservableCollection<UserViewModel>(all);
this.AllUsers.CollectionChanged += this.OnCollectionChanged;
}
public ObservableCollection<UserViewModel> AllUsers { get; private set; }
....
}
}
Following is the XAML: (A bit further than half way you'll see a ListBox called lstModules)
<UserControl.Resources>
<CollectionViewSource x:Key="UserCollection" Source="{Binding Path=AllUsers}">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="Name" Direction="Ascending" />
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
</UserControl.Resources>
<DataGrid AutoGenerateColumns="False" ItemContainerStyle="{StaticResource UserItemStyle}" AlternatingRowBackground="{x:Null}" ItemsSource="{Binding}">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Path=Name}"/>
<DataGridTextColumn Header="Job Title" Binding="{Binding Path=Job_Title}"/>
<DataGridTextColumn Header="Department" Binding="{Binding Path=Department}"/>
<DataGridTextColumn Header="Company" Binding="{Binding Path=Company}"/>
<DataGridTextColumn IsReadOnly="True" Binding="{Binding Path=Company}" CanUserResize="False" Width="580">
<DataGridTextColumn.Header>
<StackPanel Orientation="Vertical" HorizontalAlignment="Center">
<TextBlock HorizontalAlignment="Center">Modules</TextBlock>
<ListBox x:Name="lstModules" Width="190" ItemsSource="{Binding Modules}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ModuleName}"></TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</DataGridTextColumn.Header>
</DataGridTextColumn>
<DataGridTextColumn Header="Contact Detail" Binding="{Binding Path=Name}"/>
</DataGrid.Columns>
</DataGrid>
[Edit] Full XAML
<UserControl x:Class="Users.View.AllUsersView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:scm="clr-namespace:System.ComponentModel;assembly=WindowsBase"
mc:Ignorable="d"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="160" d:DesignWidth="1100">
<UserControl.Resources>
<CollectionViewSource x:Key="UserCollection" Source="{Binding Path=AllUsers}">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="Name" Direction="Ascending" />
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
<Style x:Key="UserItemStyle" TargetType="{x:Type DataGridRow}">
<!--
Stretch the content of each cell so that we can
right-align text in the Total Sales column.
-->
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<!--
Bind the IsSelected property of a ListViewItem to the
IsSelected property of a UserViewModel object.
-->
<Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}" />
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<!--
<Condition Property="ItemsControl.AlternationIndex" Value="1" />
-->
<Condition Property="IsSelected" Value="False" />
<Condition Property="IsMouseOver" Value="False" />
</MultiTrigger.Conditions>
<Setter Property="Background" Value="#EEEEEEEE" />
</MultiTrigger>
</Style.Triggers>
</Style>
<DataTemplate x:Key="headerTemplate">
<TextBlock Padding="0,0,0,0" Margin="0,0,0,0" HorizontalAlignment="Center" VerticalAlignment="Bottom" Text="{Binding}"/>
</DataTemplate>
<Style x:Key="RowHeaderStyle2" TargetType="DataGridRowsPresenter">
<Setter Property="Background" Value="{x:Null}"/>
</Style>
<Style x:Key="ColumnHeaderStyle" TargetType="DataGridColumnHeader">
<Setter Property="VerticalContentAlignment" Value="Bottom"/>
<Setter Property="VerticalAlignment" Value="Bottom"/>
<Setter Property="Height" Value="25"/>
</Style>
<Style x:Key="ModuleColumnHeaderStyle" TargetType="GridViewColumnHeader">
<Setter Property="VerticalContentAlignment" Value="Bottom"/>
<Setter Property="Width" Value="550"/>
</Style>
<Style x:Key="rotatedTextStart" TargetType="TextBlock">
<Setter Property="LayoutTransform">
<Setter.Value>
<RotateTransform Angle="-45" />
</Setter.Value>
</Setter>
<Setter Property="VerticalAlignment" Value="Bottom"/>
<Setter Property="Width" Value="130"/>
<Setter Property="Margin" Value="12,0,0,0"/>
</Style>
<Style x:Key="rotatedTextMiddle" TargetType="TextBlock">
<Setter Property="LayoutTransform">
<Setter.Value>
<RotateTransform Angle="-45" />
</Setter.Value>
</Setter>
<Setter Property="VerticalAlignment" Value="Bottom"/>
<Setter Property="Width" Value="130"/>
<Setter Property="Margin" Value="-50,0,0,0"/>
</Style>
<Style x:Key="rotatedTextEnd" TargetType="TextBlock">
<Setter Property="LayoutTransform">
<Setter.Value>
<RotateTransform Angle="-45" />
</Setter.Value>
</Setter>
<Setter Property="VerticalAlignment" Value="Bottom"/>
<Setter Property="Width" Value="130"/>
<Setter Property="Margin" Value="-50,0,12,0"/>
</Style>
<Style x:Key="ListViewItemRotatedText" TargetType="ListViewItem">
<Setter Property="LayoutTransform">
<Setter.Value>
<RotateTransform Angle="-45" />
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<DockPanel>
<Grid DockPanel.Dock="Bottom" Margin="0,2,4,2">
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal" VerticalAlignment="Center">
<TextBlock Text="Selected Users: " />
<ContentPresenter Content="{Binding Path=TotalSelectedUsers}" ContentStringFormat="0" />
<TextBlock Text=" of " />
<ContentPresenter Content="{Binding Path=TotalUsers}" ContentStringFormat="0" />
</StackPanel>
</Grid>
<DataGrid AutoGenerateColumns="False" ItemContainerStyle="{StaticResource UserItemStyle}" AlternatingRowBackground="{x:Null}" DataContext="{StaticResource UserCollection}" ItemsSource="{Binding}">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" IsReadOnly="True" HeaderStyle="{StaticResource ColumnHeaderStyle}" HeaderTemplate="{StaticResource headerTemplate}" Binding="{Binding Path=Name}"/>
<DataGridTextColumn Header="Job Title" IsReadOnly="True" HeaderStyle="{StaticResource ColumnHeaderStyle}" HeaderTemplate="{StaticResource headerTemplate}" Binding="{Binding Path=Job_Title}"/>
<DataGridTextColumn Header="Department" IsReadOnly="True" HeaderStyle="{StaticResource ColumnHeaderStyle}" HeaderTemplate="{StaticResource headerTemplate}" Binding="{Binding Path=Department}"/>
<DataGridTextColumn Header="Company" IsReadOnly="True" HeaderStyle="{StaticResource ColumnHeaderStyle}" HeaderTemplate="{StaticResource headerTemplate}" Binding="{Binding Path=Company}"/>
<DataGridTextColumn IsReadOnly="True" Binding="{Binding Path=Company}" CanUserResize="False" Width="580">
<DataGridTextColumn.Header>
<StackPanel Orientation="Vertical" HorizontalAlignment="Center">
<TextBlock HorizontalAlignment="Center">Modules</TextBlock>
<ListBox x:Name="lstModules" Width="190" ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.Modules}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ModuleName}"></TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</DataGridTextColumn.Header>
</DataGridTextColumn>
<DataGridTextColumn Header="Contact Detail" IsReadOnly="True" HeaderStyle="{StaticResource ColumnHeaderStyle}" HeaderTemplate="{StaticResource headerTemplate}" Binding="{Binding Path=Name}"/>
</DataGrid.Columns>
</DataGrid>
</DockPanel>
</UserControl>
The ListBox belongs to DataGrid control, which has it's own DataContext (AllUsers), which doesn't have Modules property. You should get Modules from UserControl's DataContext:
<ListBox x:Name="lstModules" Width="190"
ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type UserControl}},
Path=DataContext.Modules}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ModuleName}"></TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Related
I'm working on a small WPF application, when I click on a row I'm making my checkbox column selected/unselected. This is how my rows look:
And here is my code:
private void dtgTest_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (dtgTest.SelectedItem != null)
{
CheckBox checkbocColumn = (dtgTest.Columns[3].GetCellContent(dtgTest.SelectedItem) as CheckBox);
checkbocColumn.IsChecked = !checkbocColumn.IsChecked;
var selectedItem = (BillItemInSerie)dtgTest.SelectedItem;
var obj = serialNumbersIn.FirstOrDefault(sn => selectedItem.DocumentItemInSeriesId == sn.DocumentItemInSeriesId);
obj.IsChecked= (bool)checkbocColumn.IsChecked;
}
}
Here is how I'm filling DataGrid:
public Test_Window()
: this()
{
databaseValues = Controller.Instance.GetById(Id);
dtgTest.ItemsSource = null;
dtgTest.ItemsSource = databaseValues;
}
So when form is generated I acctually get all items from DB
And here is my XAML:
<DataGrid Name="dtgTest" IsReadOnly="True" VirtualizingStackPanel.VirtualizationMode="Standard" EnableColumnVirtualization = "True" EnableRowVirtualization ="True" MaxWidth="4000" MaxHeight="2000" Background="White" Margin="5,5,5,0" AutoGenerateColumns="False" RowHeaderWidth="0" HorizontalGridLinesBrush="#0091EA" VerticalGridLinesBrush="#0091EA" CanUserAddRows="False" RowHeight="30" Grid.ColumnSpan="2" Grid.Row="2" SelectionChanged="dtgTest_SelectionChanged">
<DataGrid.CellStyle>
<StaticResource ResourceKey="DataGridCentering"/>
</DataGrid.CellStyle>
<DataGrid.Resources>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="Background" Value="#0091EA"/>
<Setter Property="Opacity" Value="1"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="FontSize" Value="{x:Static local:Globals.dataGridfontSizeHeader}"/>
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="Height" Value="40"/>
</Style>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}"
Color="LightBlue"/>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Value1}" Header="" Foreground="Black" FontSize="15" FontFamily="Verdana" Width="35*" />
<DataGridTextColumn Binding="{Binding Value2}" Header="" Foreground="Black" FontSize="15" FontFamily="Verdana" Width="35*" />
<DataGridTextColumn x:Name="colFormatedDate" Binding="{Binding ExpireDate, StringFormat ={}{0:MM/yyyy}}" Header="" Foreground="Black" FontSize="15" FontFamily="Verdana" Width="20*" />
<DataGridCheckBoxColumn x:Name="colSelektiraj" Binding="{Binding IsChecked}" Header="" Width="10*" />
</DataGrid.Columns>
</DataGrid>
But issue is here when I click on a row and make checkbox column selected (LIKE IN EXAMPLE IMAGE ABOVE) , and If I immediately change my mind and click again on selected row to change the state of checkbox column I won't be able to do it, because dtgTest_SelectionChanged won't trigger because I did not change selection..
So I guess detecting if a row is clicked might help me here? So I might execute similar code as it is in dtgTest_SelectionChanged event?
Any kind of help would be awesome!
Thanks, guys
Cheers
EDIT AFTER Rekshino help:
<DataGrid Name="dtgTest" IsReadOnly="True" VirtualizingStackPanel.VirtualizationMode="Standard" EnableColumnVirtualization = "True" EnableRowVirtualization ="True" MaxWidth="4000" MaxHeight="2000" Background="White" Margin="5,5,5,0" AutoGenerateColumns="False" RowHeaderWidth="0" HorizontalGridLinesBrush="#0091EA" VerticalGridLinesBrush="#0091EA" CanUserAddRows="False" RowHeight="30" Grid.ColumnSpan="2" Grid.Row="2" SelectionChanged="dtgTest_SelectionChanged" PreviewMouseDown="dtgTest_PreviewMouseDown">
<DataGrid.CellStyle>
<StaticResource ResourceKey="DataGridCentering"/>
</DataGrid.CellStyle>
<DataGrid.Resources>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="Background" Value="#0091EA"/>
<Setter Property="Opacity" Value="1"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="FontSize" Value="{x:Static local:Globals.dataGridfontSizeHeader}"/>
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="Height" Value="40"/>
</Style>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="LightBlue"/>
<Style TargetType="DataGridCell">
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="dtgTest_PreviewMouseDown"/>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Value1}" Foreground="Black" FontSize="15" FontFamily="Verdana" Width="35*" />
<DataGridTextColumn Binding="{Binding Value2}" Foreground="Black" FontSize="15" FontFamily="Verdana" Width="35*" />
<DataGridTextColumn x:Name="colFormatedDate" Binding="{Binding ExpireDate, StringFormat ={}{0:MM/yyyy}}" Foreground="Black" FontSize="15" FontFamily="Verdana" Width="20*" />
<DataGridCheckBoxColumn x:Name="colSelektiraj" Binding="{Binding IsChecked, NotifyOnTargetUpdated=True}" Header="" Width="10*" />
</DataGrid.Columns>
</DataGrid>
C# :
private void dtgTest_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
var cell = sender as DataGridCell;
if (cell == null)
{
return;
}
DataGridRow parGridRow = null;
var visParent = VisualTreeHelper.GetParent(cell);
while (parGridRow == null && visParent != null)
{
parGridRow = visParent as DataGridRow;
visParent = VisualTreeHelper.GetParent(visParent);
}
if (parGridRow == null) { return; }
var selectedItem = (parGridRow.DataContext as BillItemInSerie);
var obj = serialNumbersIn.FirstOrDefault(sn => selectedItem.DocumentItemInSeriesId == sn.DocumentItemInSeriesId);
obj.IsChecked = (bool)!obj.IsChecked;
}
You can set mouse event handler for the cell, get the row and make what you want with it. I have removed event handler for SelectionChanged, because you don't need it in this solution.
<DataGrid Name="dtgTest" IsReadOnly="True" VirtualizingStackPanel.VirtualizationMode="Standard" EnableColumnVirtualization = "True" EnableRowVirtualization ="True" MaxWidth="4000" MaxHeight="2000" Background="White" Margin="5,5,5,0" AutoGenerateColumns="False" RowHeaderWidth="0" HorizontalGridLinesBrush="#0091EA" VerticalGridLinesBrush="#0091EA" CanUserAddRows="False" RowHeight="30" Grid.ColumnSpan="2" Grid.Row="2">
<DataGrid.Resources>
<Style TargetType="DataGridCell">
<!-- If you have to apply another style, then use BasedOn-->
<!--<Style TargetType="DataGridCell" BasedOn="{StaticResource DataGridCentering}">-->
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="PreviewMouseDown"/>
</Style>
</DataGrid.Resources>
...
</DataGrid>
private void PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
var cell = sender as DataGridCell; if (cell == null) { return; }
DataGridRow parGridRow = null;
var visParent = VisualTreeHelper.GetParent(cell);
while (parGridRow == null && visParent != null)
{
parGridRow = visParent as DataGridRow;
visParent = VisualTreeHelper.GetParent(visParent);
}
if (parGridRow == null) { return; }
var selectedItem = (parGridRow.DataContext as BillItemInSerie);
var obj = serialNumbersIn.FirstOrDefault(sn => selectedItem.DocumentItemInSeriesId == sn.DocumentItemInSeriesId);
obj.IsChecked= (bool)!obj.IsChecked;
//e.Handled = true;
}
If you have a ViewModel (MVVM) which represents the Data for each row. You should/could have a bool property there which represents the CheckBox state (rather than doing so from code behind).
Next, you can Bind DataGrid's SelectedItem to an Object (of relevant type) and test whether that gets fired even when you click same item multiple times. If it does (at least in DevExpress gridControls) - You should Flip the bool property in the Setter for the SelectedItem.
hi you can set a flag on the binding at the checkboxcolumn.
There is a NotifyOnTargetUpdated with fires an TargetUpdated event when the target (your checkbox) changes.
With NotifyOnTargetUpdated=True on your binding you activate them.
Your DataGridCheckBoxColumn looks then like this:
<DataGridCheckBoxColumn x:Name="colSelektiraj" Binding="{Binding IsChecked, NotifyOnTargetUpdated=True}" Header="" Width="10*" />
On the Datagrid use the TargetUpdated="DataGrid_TargetUpdated"event to get notified. Your datagrid looks then like this:
<DataGrid Name="dtgTest" IsReadOnly="True" TargetUpdated="DataGrid_TargetUpdated" ...>
To get notified when the selection changed use the SelectionChanged event as you did it already.
I implemented:
<DataGrid Name="DataGridProcesso" AutoGenerateColumns="False" ItemsSource="{Binding CollectionView}" CanUserReorderColumns="False" CanUserSortColumns="True" AlternatingRowBackground="#D1DFE7" IsSynchronizedWithCurrentItem="True">
<DataGrid.InputBindings>
<MouseBinding MouseAction="LeftDoubleClick"
Command="{Binding ItemDoubleClickCommand}" />
</DataGrid.InputBindings>
...
But the DoubleClick only work if I Click six times (3 double click)
I think the first click occurs in inner cell, after cell and finally in row (I only think, I haven't certain about that), I just want when LeftDoubleClick occurs in cell trigger my event.
What is wrong?
My full code of DataGrid:
<DataGrid Name="DataGridProcesso" AutoGenerateColumns="False" ItemsSource="{Binding CollectionView}" CanUserReorderColumns="False" CanUserSortColumns="True" AlternatingRowBackground="#D1DFE7" IsSynchronizedWithCurrentItem="True">
<DataGrid.InputBindings>
<MouseBinding MouseAction="LeftDoubleClick" Command="{Binding ItemDoubleClickCommand}" />
</DataGrid.InputBindings>
<DataGrid.Resources>
<Style TargetType="{x:Type DataGridRow}">
<Setter Property="Padding" Value="0,10,0,10" />
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0,0,0,0"/>
</Style>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="BorderBrush" Value="#CCC"/>
<Setter Property="BorderThickness" Value="0,0,1,0"/>
<Setter Property="Cursor" Value="Hand" />
<Setter Property="FontFamily" Value="Segoe" />
<Setter Property="FontSize" Value="14" />
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTemplateColumn Header="Data" Width="Auto" HeaderStyle="{StaticResource DataGridColumnHeaderStyle}">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label Content="{Binding Path=Data,Mode=OneTime}" ToolTip="Data" HorizontalAlignment="Right"></Label>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Número" Width="Auto" HeaderStyle="{StaticResource DataGridColumnHeaderStyle}">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label Content="{Binding Path=Numero,Mode=OneTime}" ToolTip="Número"></Label>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Descrição" Width="*" HeaderStyle="{StaticResource DataGridColumnHeaderStyle}">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label Content="{Binding Path=Descricao, Mode=OneTime}" ToolTip="Descrição"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Andamento" Width="Auto" HeaderStyle="{StaticResource DataGridColumnHeaderStyle}">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label Content="{Binding Path=Andamento.Descricao, Mode=OneTime}" ToolTip="Andamento"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Lembrete" Width="Auto" HeaderStyle="{StaticResource DataGridColumnHeaderStyle}">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label Content="{Binding Path=Lembrete, Mode=OneTime}" ToolTip="Lembrete"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
Part of ViewModel:
private ObservableCollection<Processo> _processos;
public ObservableCollection<Processo> Processos
{
get { return _processos; }
set
{
if (value != _processos)
{
_processos = value;
NotifyPropertyChanged(nameof(Processos));
}
}
}
private ICollectionView _collectionView;
public ICollectionView CollectionView
{
get
{
return _collectionView;
}
set
{
_collectionView = value;
NotifyPropertyChanged(nameof(CollectionView));
}
}
public ICommand ItemDoubleClickCommand => new Command<MainWindowViewModel>(a =>
{
AlterarProcesso((Processo)CollectionView.CurrentItem);
});
Try adding IsSynchronizedWithCurrentItem="True" to your DataGrid properties.
Then add CommandParameter="{Binding CollectionView/}".
<DataGrid Name="DataGridProcesso" IsSynchronizedWithCurrentItem="True" AutoGenerateColumns="False" ItemsSource="{Binding CollectionView}" CanUserReorderColumns="False" CanUserSortColumns="True" AlternatingRowBackground="#D1DFE7" IsSynchronizedWithCurrentItem="True">
<DataGrid.InputBindings>
<MouseBinding MouseAction="LeftDoubleClick"
Command="{Binding ItemDoubleClickCommand}"
CommandParameter="{Binding CollectionView/}"/>
</DataGrid.InputBindings>
Note the / in the CommandParameter This ensures it binds to the current item.
Then when this is used with IsSynchronizedWithCurrentItem="True" it ensures that it binds to the selected item.
<DataGrid AutoGenerateColumns="False" Height="330" HorizontalAlignment="Left" Margin="5,70,0,0" Name="grdDeviceInfo" VerticalAlignment="Top"
CanUserAddRows="False" IsReadOnly="True" Width="368" HorizontalScrollBarVisibility="Auto">
<DataGrid.Columns>
<DataGridTextColumn Header="Channels" Width="100" Binding="{Binding ChannelNo}"></DataGridTextColumn>
<DataGridTextColumn Header="Label" Width="200" Binding="{Binding Label}"></DataGridTextColumn>
<DataGridTemplateColumn Header="Status" Width="60">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Ellipse Height="13" Name="grdfEllipse" Stroke="Black" Fill="{}" Width="20"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
Code Behind:
List<IOInformation> lstIOStatus = new List<IOInformation>();
for (int i = 0; i < channelStatus.Count(); i++)
{
// var columns = line.Split('\t');
lstIOStatus.Add(new IOInformation
{
ChannelNo = "Channel " + j++,
Label = labeldata[i],
MasterStatus = Convert.ToBoolean(channelStatus[i])
});
}
this.grdDeviceInfo.ItemsSource = lstIOStatus;
I want to change the Ellipse color to green if it is true, or red if it is false.
You can use triggers to do this. Here is a link on how top use them :
http://www.wpf-tutorial.com/styles/trigger-datatrigger-event-trigger/
Your xaml code would look like this :
<Ellipse Height="13" Name="grdfEllipse" Stroke="Black" Width="20">
<Ellipse.Style>
<Setter Property="Fill" Value="Red"/>
<Style TargetType="Ellipse">
<Style.Triggers>
<DataTrigger Binding="{Binding yourBinding}" Value="true">
<Setter Property="Fill" Value="Green"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
I am trying to show different Groups in a Listview which contain an expander and a header. However I don't want my SecondLevel Group to show a header if the Group only contains 1 item.
Since this would be quite inconvenient.
My Code:
<Window x:Class="ListViewGrouping.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:listViewGrouping="clr-namespace:ListViewGrouping"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<listViewGrouping:GroupItemStyleSelector x:Key="groupItemStyleSelector"/>
<!-- Style for the first level GroupItem -->
<Style x:Key="FirstLevel" TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander IsExpanded="True">
<Expander.Header>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Margin="3.5,0" Text="{Binding Name}" TextBlock.FontWeight="Bold"/>
<TextBlock Grid.Column="1" Margin="3.5,0" Text="Elements:"/>
<TextBlock Grid.Column="2" Margin="3.5,0" Text="{Binding ItemCount}"/>
</Grid>
</Expander.Header>
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Style for the second level GroupItem -->
<Style x:Key="SecondLevel" TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander IsExpanded="True" Margin="15,0,0,0">
<Expander.Header>
<TextBlock Text="{Binding Name}" TextBlock.FontWeight="Bold"/>
</Expander.Header>
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<ListView Name="mailView" ItemsSource="{Binding}">
<ListView.GroupStyle>
<GroupStyle ContainerStyleSelector="{StaticResource groupItemStyleSelector}" />
</ListView.GroupStyle>
<ListView.View>
<GridView>
<GridViewColumn Header="ID" DisplayMemberBinding="{Binding ID}"/>
<GridViewColumn Header="Subject" DisplayMemberBinding="{Binding Subject}"/>
<GridViewColumn Header="Sender" DisplayMemberBinding="{Binding Sender}"/>
<GridViewColumn Header="Support-ID" DisplayMemberBinding="{Binding Support_ID}"/>
<GridViewColumn Header="Supporter" DisplayMemberBinding="{Binding Supporter}"/>
<GridViewColumn Header="Received" DisplayMemberBinding="{Binding ReceivedDate}"/>
</GridView>
</ListView.View>
</ListView>
</Grid>
Code behind:
private void createMailList()
{
_mails.Add(new Mail("LIC", "Lizenz geht nicht", "Xeun", "LIC.2013.01.10.002", "Xeun", "25.09.2013"));
_mails.Add(new Mail("CD", "Alles doof", "Xeun", "CD.2013.01.10.002", "Xeun", "25.09.2013"));
_mails.Add(new Mail("CD", "Re:Alles doof", "Xeun", "CD.2013.01.10.002", "Xeun", "25.09.2013"));
_mails.Add(new Mail("CD", "CD kaputt", "Xeun", "CD.2013.01.10.003", "Xeun", "25.09.2013"));
_mails.Add(new Mail("CD", "Geht nicht", "Xeun", "CD.2013.01.10.001", "Xeun", "25.09.2013"));
_mails.Add(new Mail("LIC", "Kaputt", "Xeun", "LIC.2013.01.10.001", "Xeun", "25.09.2013"));
}
public MainWindow()
{
InitializeComponent();
createMailList();
DataContext = _mails;
ICollectionView view = CollectionViewSource.GetDefaultView(_mails);
PropertyGroupDescription groupDescription = new PropertyGroupDescription("ID");
view.GroupDescriptions.Add(groupDescription);
view.GroupDescriptions.Add(new PropertyGroupDescription("Support_ID"));
}
}
public class GroupItemStyleSelector : StyleSelector
{
public override Style SelectStyle(object item, DependencyObject container)
{
Style s;
CollectionViewGroup group = item as CollectionViewGroup;
Window window = Application.Current.MainWindow;
if (!group.IsBottomLevel)
{
s = window.FindResource("FirstLevel") as Style;
}
else
{
s = window.FindResource("SecondLevel") as Style;
}
return s;
}
}
I hope I explained my problem well enough - I have attached a screenshot of the small app - the Groups marked as red only contain one item and should not be shown as group.
For both styles split the ControlTemplate in 2, one with an expander and one with out.
Create a converter which checks the if the group size (your group is of type CollectionViewGroup)
return yourGroup.Items.Count > 1
Place a DataTrigger as seen below in each style which checks the groups size via the converter
(your DataContext is your group so the binding is Binding="{Binding}"
xaml :
<ControlTemplate TargetType="{x:Type GroupItem}" x:Key="withExpander">
<Expander IsExpanded="True">
<Expander.Header>
.....
</Expander.Header>
<ItemsPresenter />
</Expander>
</ControlTemplate>
<ControlTemplate TargetType="{x:Type GroupItem}" x:Key="withOutExpander">
<ItemsPresenter />
</ControlTemplate>
<Style x:Key="FirstLevel" TargetType="{x:Type GroupItem}">
<Setter Property="Template" Value="{StaticResource withExpander}" />
<Style.Triggers>
<DataTrigger Binding="{Binding , Converter={StaticResource GroupSizeToExpanderConverter}" Value="False">
<Setter Property="Template" Value="{StaticResource withOutExpander}"/>
</DataTrigger>
</Style.Triggers>
</Style>
Edit :
*the converter value will be the Group itself (of type CollectionViewGroup)
The Converter :
public class GroupSizeToExpanderConverter: IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
CollectionViewGroup grp = (CollectionViewGroup)value;
return grp.Items.Count() > 1; // ALTERNATIVLY grp.ItemCount;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
here is my solution
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<Expander IsExpanded="True">
<Expander.Style>
<Style TargetType="Expander">
<Setter Property="Visibility" Value="Visible"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding ItemCount}" Value="1">
<Setter Property="Visibility" Value="Collapsed"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Expander.Style>
<Expander.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" FontWeight="Bold" Foreground="Gray" FontSize="22" VerticalAlignment="Bottom" />
<TextBlock Text="{Binding ItemCount}" FontSize="22" Foreground="Green" FontWeight="Bold" FontStyle="Italic" Margin="10,0,0,0" VerticalAlignment="Bottom" />
<TextBlock Text=" item(s)" FontSize="22" Foreground="Silver" FontStyle="Italic" VerticalAlignment="Bottom" />
</StackPanel>
</Expander.Header>
<Border BorderBrush="LightBlue" BorderThickness="2" Margin="0 2">
<ItemsPresenter />
</Border>
</Expander>
<ItemsPresenter>
<ItemsPresenter.Style>
<Style TargetType="ItemsPresenter">
<Setter Property="Visibility" Value="Collapsed"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding ItemCount}" Value="1">
<Setter Property="Visibility" Value="Visible"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ItemsPresenter.Style>
</ItemsPresenter>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
In my WPF DataGrid , I have a problem while sorting the row.
I am setting the new Style from code behind , while datagrid loaded event Name .
But when i click on the Header for the sorting my DataGrid Style changes to the default.
My code for DataGrid :-
<DataGrid x:Name="dtstandardview" BorderThickness="0" Height="429" Width="688" BorderBrush="Aqua" MouseLeftButtonDown="dtstandardview_MouseRightButtonUp_1"
GridLinesVisibility="None" MouseRightButtonUp="dtstandardview_MouseRightButtonUp_1"
VerticalScrollBarVisibility="Visible" AutoGenerateColumns="False" IsReadOnly="True"
CanUserDeleteRows="False" AlternationCount="2" CanUserResizeRows="False" Sorting="dtstandardview_Sorting_1"
Background="#DCDCDC" HeadersVisibility="Column" CanUserResizeColumns="False"
RowHeight="27" SelectionUnit="FullRow" CanUserAddRows="False" MinRowHeight="27" LoadingRow="dtstandardview_LoadingRow" LoadingRowDetails="dtstandardview_LoadingRowDetails" Loaded="dtstandardview_Loaded" Initialized="dtstandardview_Initialized" CellEditEnding="dtstandardview_CellEditEnding" AutoGeneratingColumn="dtstandardview_AutoGeneratingColumn" UnloadingRow="dtstandardview_UnloadingRow" UnloadingRowDetails="dtstandardview_UnloadingRowDetails" >
<DataGrid.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect BlurRadius="0" Color="#FF000000" Direction="-60" Opacity="0.32" ShadowDepth="1"/>
</Setter.Value>
</Setter>
<Setter Property="Margin" Value="10,5" />
<Setter Property="VerticalContentAlignment" Value="Bottom"/>
</Style>
</DataGrid.CellStyle>
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<Setter Property="FontSize" Value="12"/>
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="Foreground" Value="#404040"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="DataContext">
<Setter.Value>
<TextBlock Margin="10,0,0,0" TextWrapping="Wrap" Text="{Binding}">
<TextBlock.Effect>
<DropShadowEffect BlurRadius="0" Color="#FF000000" Direction="-60" Opacity="0.32" ShadowDepth="1"/>
</TextBlock.Effect>
</TextBlock>
</Setter.Value>
</Setter>
</Style>
</DataGrid.RowStyle>
<DataGrid.RowBackground >
<ImageBrush ImageSource="/ClientApplication;component/Images/second_row_bg.png"/>
</DataGrid.RowBackground>
<DataGrid.AlternatingRowBackground>
<ImageBrush ImageSource="/ClientApplication;component/Images/bonus_progress_bg.png"/>
</DataGrid.AlternatingRowBackground>
<DataGrid.ColumnHeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="ContentTemplate" >
<Setter.Value>
<DataTemplate>
<TextBlock Foreground="#404040" FontWeight="Bold" Margin="10,0,0,0" TextWrapping="Wrap" Text="{Binding}" TextOptions.TextFormattingMode="Display">
<TextBlock.Effect>
<DropShadowEffect BlurRadius="0" Color="#FFFFFF" Direction="-90" Opacity="0.40" ShadowDepth="1" RenderOptions.ClearTypeHint="Auto" />
</TextBlock.Effect>
</TextBlock>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="Background">
<Setter.Value>
<ImageBrush ImageSource="/ClientApplication;component/Images/table_bg_header.png"/>
</Setter.Value>
</Setter>
<Setter Property="BorderBrush">
<Setter.Value>
<ImageBrush ImageSource="/ClientApplication;component/Images/titel_bg.png"/>
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="#404040" />
<Setter Property="BorderThickness" Value="0, 0, 1, 0"/>
<Setter Property="Height" Value="26" />
<Setter Property="FontSize" Value="14"/>
<Setter Property="FontFamily" Value="Arial"/>
</Style>
</DataGrid.ColumnHeaderStyle>
<DataGrid.Columns>
<DataGridTextColumn Width="125" Header="Table" Binding="{Binding Path=Table}">
</DataGridTextColumn>
<DataGridTextColumn Width="101" Header="Stakes" Binding="{Binding Path=Stakes}" />
<DataGridTextColumn Width="95" Header="Game" Binding="{Binding Path=Game}" />
<DataGridTemplateColumn Header="Type" Width="86">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate x:Name="typedatatempl">
<StackPanel Orientation="Horizontal" Name="stackpaneltype">
<TextBlock Name="typedate" Text="{Binding Path=Type}" Margin="2,0,0,2" />
<TextBlock Name="txtblocknumber" Text="{Binding Path=number}" Margin="2, 0, 0, 2" Background="Gray" TextAlignment="Center" FontFamily="Arial" FontWeight="Bold" FontSize="10" Foreground="White" Height="13" Width="13" VerticalAlignment="Center" HorizontalAlignment="Center" />
<TextBlock Name="txtblockalpha" Text="{Binding Path=alphabate}" Margin="5,0,0,2" Background="Yellow" FontFamily="Arial" TextAlignment="Center" FontWeight="Bold" FontSize="10" Foreground="White" Height="13" Width="13" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Width="83" Header="Players" Binding="{Binding Path=Players}" />
<DataGridTextColumn Width="117" Header="Average Pot" Binding="{Binding Path=Average}" />
<DataGridTextColumn Width="63" Header="H/Hr" Binding="{Binding Path=hhr}" />
</DataGrid.Columns>
</DataGrid>
dataGrid.xaml.cs
int i = e.Row.GetIndex();
// SetDatGrid();
// to get the all the row one by one.
DataGridRow objrow = new DataGridRow();
DataGridCell objcell = new DataGridCell();
// objrow = ExtensionMethods.GetRow(dtstandardview, i);
objcell = ExtensionMethods.GetCell(dtstandardview, e.Row, 3);
ContentPresenter objcontent = new ContentPresenter();
if (objcell != null)
{
objcontent = (ContentPresenter)objcell.Content;
GameClassTemp objGameClassTemp = new GameClassTemp();
objGameClassTemp = (GameClassTemp)objcontent.Content;
ContentPresenter cp = dtstandardview.ItemContainerGenerator.ContainerFromItem(objcell) as ContentPresenter;
StackPanel objstackpanel = ExtensionMethods.FindVisualChild<StackPanel>((ContentPresenter)objcell.Content);
TextBlock objtypedate = (TextBlock)objstackpanel.FindName("typedate");
TextBlock objtxtblocknumber = (TextBlock)objstackpanel.FindName("txtblocknumber");
TextBlock objtxtblockalpha = (TextBlock)objstackpanel.FindName("txtblockalpha");
if (objGameClassTemp != null)
{
if (objGameClassTemp.alphabate != null && objGameClassTemp.alphabate.Trim().Length > 0)
{
var bc = new BrushConverter();
switch (objGameClassTemp.number)
{
case "1":
objtxtblockalpha.Background = Brushes.Green;
break;
case "2":
objtxtblockalpha.Background = Brushes.Yellow;
break;
case "3":
objtxtblockalpha.Background = Brushes.Red;
break;
case "4":
objtxtblockalpha.Background = (Brush)bc.ConvertFrom("#85ab33");
break;
case "5":
//objtxtblockalpha.Background = Brushes.Pink;
objtxtblockalpha.Background = (Brush)bc.ConvertFrom("#f9572a");
break;
case "6":
objtxtblockalpha.Background = (Brush)bc.ConvertFrom("#e0d921");
break;
default:
objtxtblockalpha.Background = Brushes.YellowGreen;
break;
}
}
else
{
objtxtblockalpha.Background = Brushes.Transparent;
}
}
}
You need to use LoadingDataRow event
dataGrid.LoadingRow += dataGrid_LoadingRow;
void dataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
{
var dataContext = e.Row.DataContext;
}