Caliburn Micro Datagrid Context Menu - c#

My items from context menu are not executing.
My xaml:
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:arFirmaKomp.Views"
xmlns:arFirmaKomp="clr-namespace:arFirmaKomp" x:Class="arFirmaKomp.Views.ArKlienciView"
xmlns:helpers="clr-namespace:arFirmaKomp.ViewHelpers"
xmlns:cal="http://www.caliburnproject.org"
mc:Ignorable="d" Height="600" Width="1200" >
<Grid>
<ComboBox x:Name="ArKlienciList" SelectedItem="{Binding Path=WybranyArKlient, Mode=OneWayToSource}" DisplayMemberPath="PodmiotyOdbiorcaNazwaSkrocona" HorizontalAlignment="Left" Margin="128,49,0,0" VerticalAlignment="Top" Width="134" Height="22" />
<DataGrid x:Name="ArKlienciList2" ItemsSource="{Binding Path=ArKlienciICView}" SelectedItem="{Binding SelectedItem}"
cal:Message.Attach="[Event CellEditEnding]=[Action SaveChanges()];[Event MouseDoubleClick] = [Action RowSelect()]"
RowDetailsVisibilityMode="VisibleWhenSelected" Margin="17,80,10,20" EnableRowVirtualization="True" AutoGenerateColumns="False"
Tag="{Binding DataContext, RelativeSource={RelativeSource Self}}" >
<DataGrid.Resources>
<helpers:BindingProxy x:Key="proxy" Data="{Binding}" />
<ContextMenu x:Key="ContextMenu" cal:Action.TargetWithoutContext="{Binding}" IsOpen="{Binding Data.IsContextMenuOpen, Source={StaticResource proxy}}">
<MenuItem Header="Open"
cal:Message.Attach="Open($dataContext)">
</MenuItem>
</ContextMenu>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn x:Name="idColumn" Width="SizeToHeader" Header="Id" Binding="{Binding Id}"/>
<DataGridTextColumn x:Name="nexoKlientNabywcaColumn" Width="SizeToHeader" Header="Nexo Klient Nabywca" Binding="{Binding PodmiotyNabywcaNazwaSkrocona,Mode=OneWay}">
</DataGridTextColumn>
<DataGridTextColumn x:Name="nexoKlientOdbiorcaColumn" Width="SizeToHeader" Header="Nexo Klient Odbiorca" Binding="{Binding PodmiotyOdbiorcaNazwaSkrocona,Mode=OneWay}"/>
<DataGridTextColumn x:Name="nexoKlientOdbiorcaTelefonColumn" Width="SizeToHeader" Header="Nexo Odbiorca Telefon" Binding="{Binding OdbiorcaTelefon,Mode=OneWay}"/>
</DataGrid.Columns>
<DataGrid.RowStyle>
<Style TargetType="DataGridRow" BasedOn="{StaticResource {x:Type DataGridRow}}">
<Setter Property="ContextMenu" Value="{StaticResource ContextMenu}" />
</Style>
</DataGrid.RowStyle>
</DataGrid>
<TextBox HorizontalAlignment="Left" x:Name="FilterString" Height="19" Margin="128,15,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="134"/>
<Label Content="filtr odbiorca" HorizontalAlignment="Left" Height="26" Margin="17,15,0,0" VerticalAlignment="Top" Width="92"/>
</Grid>
My viewmodel - contextmenu part:
public void Open(object source)
{
MessageBox.Show((string)source);
}
My bindingProxy is taken from Thomas Levesque Blog
I can see this context menu, and as I saw in other similar posts context menu is not connected with my ViewModel, and I don't know how to connect it. Contextmenu should make some action with the selected row as a parameter.

Related

Get data from DataGrid if DataGridCheckBoxColumn is checked

I have this XAML:
<Window x:Name="Form" x:Class="SanityArchiver.DesktopUI.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SanityArchiver.DesktopUI.Views"
xmlns:forms="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
mc:Ignorable="d"
Title="Sanity Archiver" Height="450" Width="800">
<Grid x:Name="MainWindow1" Loaded="Window_Loaded">
<Grid.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Directory}" ItemsSource ="{Binding Directories}">
<TextBlock Text="{Binding Path=Name}" MouseDown="NameCol_mousedown"/>
</HierarchicalDataTemplate>
</Grid.Resources>
<TreeView Margin="12,12,0,12" Name="treeView1" HorizontalAlignment="Left" Width="204" >
<TreeViewItem ItemsSource="{Binding Directories}" Header="Choose directory"/>
</TreeView>
<DataGrid x:Name="FilesDataGrid" AutoGenerateColumns="False" Margin="234,12,10.286,50.714">
<DataGrid.Columns>
<DataGridCheckBoxColumn x:Name="CheckBox" Header="" Binding="{Binding IsChecked}"/>
<DataGridTextColumn IsReadOnly="True" Binding="{Binding FileName}" Header="Name" Width="200"/>
<DataGridTextColumn IsReadOnly="True" Binding="{Binding Created}" Header="Created" Width="200"/>
<DataGridTextColumn IsReadOnly="True" Binding="{Binding Size}" Header="Size(kb)" Width="200"/>
</DataGrid.Columns>
</DataGrid>
<Button x:Name="CompressButton" Content="Compress" HorizontalAlignment="Left" Margin="234,389,0,0" VerticalAlignment="Top" Width="75" Click="CompressButton_Click"/>
</Grid>
</Window>
And if the CheckBox is checked(it can be one file or any number) and I click the "Compress" button, I would like to get back the rows which is checked. If it isn't doable in DataGrid, could you point me in another direction?
Thanks

MVVM binding not working in DataGrid column header when inside non-primary TabItem

I have a DataGrid inside a secondary TabItem and I wanted to bind some data from the view model to the header. I was able to bind data to the header of the DataGrid in the primary TabItem but the same code doesn't work for the secondary TabItem. I followed the answer for the following question but it still isn't working and I'm not sure what is wrong. I'm not really sure if my data context is incorrect or if my binding is not set up correctly.
Binding not working in DataGrid column header when inside non-primary TabItem
Here is my code:
XAML
<Window xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
x:Class="TestWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="Test Window" Height="645" Width="900">
<StackPanel Orientation="Vertical">
<TabControl>
<TabItem Name="Primary_Tab" Header="Primary Tab">
<!--Mock Data Grid-->
</TabItem>
<TabItem Name="Secondary_Tab" Header="Secondary Tab">
<DataGrid Height="500" ItemsSource="{Binding GridDetails}" HorizontalAlignment="Left" VerticalAlignment="Top" AutoGenerateColumns="False" CanUserAddRows="False">
<DataGrid.Resources>
<local:BindingProxy x:Key="proxy" Data="{Binding}" />
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn x:Name="Name" Header="Name" Binding="{Binding Path='Name', Mode=OneTime}" IsReadOnly="True" Width="200" />
<DataGridTextColumn x:Name="ID" Header="ID" Binding="{Binding Path='ID', Mode=OneTime}" IsReadOnly="True" Width="100">
<DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="HorizontalAlignment" Value="Center" />
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
<DataGridTextColumn x:Name="NumClaims" Binding="{Binding Path='NumClaims', Mode=OneTime}" IsReadOnly="True" Width="100">
<DataGridTextColumn.Header>
<StackPanel>
<TextBlock Text="Claims"/>
<TextBlock DataContext="{Binding RelativeSource={RelativeSource AncestorType=DataGrid, Mode=FindAncestor}, Path=DataContext}" Text="{Binding TotalClaims, UpdateSourceTrigger=PropertyChanged, Source={StaticResource proxy}}"/>
</StackPanel>
</DataGridTextColumn.Header>
<DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="HorizontalAlignment" Value="Center" />
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
<DataGridTextColumn x:Name="NewClaims" Binding="{Binding Path='NumNewClaims', Mode=OneTime}" IsReadOnly="True" Width="80">
<DataGridTextColumn.Header>
<StackPanel>
<TextBlock Text="New Claims"/>
<TextBlock DataContext="{Binding RelativeSource={RelativeSource AncestorType=DataGrid, Mode=FindAncestor}, Path=DataContext}" Text="{Binding TotalNewClaims, UpdateSourceTrigger=PropertyChanged, Source={StaticResource proxy}}"/>
</StackPanel>
</DataGridTextColumn.Header>
<DataGridTextColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Background" Value="{Binding NumNewClaims}"/>
</Style>
</DataGridTextColumn.CellStyle>
<DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="HorizontalAlignment" Value="Center" />
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</TabItem>
</TabControl>
</StackPanel>
</Window>
View Model
public class TestWindowViewModel : ViewModelBase
{
private ObservableCollection<GridDetailModel> _gridDetails;
public ObservableCollection<GridDetailModel> GridDetails
{
get
{
return _gridDetails;
}
set
{
SetProperty(ref _gridDetails, value);
}
}
private string _totalClaims = "0";
public string TotalClaims
{
get
{
return _totalClaims;
}
set
{
SetProperty(ref _totalClaims, value);
}
}
private string _totalNewClaims = "0";
public string TotalNewClaims
{
get
{
return _totalNewClaims;
}
set
{
SetProperty(ref _totalNewClaims, value);
}
}
}
Binding Proxy Class
public class BindingProxy : Freezable
{
#region Overrides of Freezable
protected override Freezable CreateInstanceCore()
{
return new BindingProxy();
}
#endregion
public object Data
{
get { return (object)GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
// Using a DependencyProperty as the backing store for Data. This enables animation, styling, binding, etc...
public static readonly DependencyProperty DataProperty =
DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
}
Any help would be greatly appreciated.
I finally managed to fix the binding issues. It seems like I had a bunch of unnecessary binding context code that was interfering with the proxy binding. For anyone who is having the same issue in the future this is what worked for me. Note that I didn't have to change the view model or the BindingProxy class at all. Just needed some work on the XAML portion.
<Window xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
x:Class="TestWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mxlns:local="clr-namespace:MyNamespace"
mc:Ignorable="d"
Title="Test Window" Height="645" Width="900">
<StackPanel Orientation="Vertical">
<TabControl>
<TabItem Name="Primary_Tab" Header="Primary Tab">
<!--Mock Data Grid-->
</TabItem>
<TabItem Name="Secondary_Tab" Header="Secondary Tab">
<DataGrid Height="500" ItemsSource="{Binding GridDetails}" HorizontalAlignment="Left" VerticalAlignment="Top" AutoGenerateColumns="False" CanUserAddRows="False">
<DataGrid.Resources>
<local:BindingProxy x:Key="proxy" Data="{Binding}" />
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn x:Name="Name" Header="Name" Binding="{Binding Path='Name', Mode=OneTime}" IsReadOnly="True" Width="200" />
<DataGridTextColumn x:Name="ID" Header="ID" Binding="{Binding Path='ID', Mode=OneTime}" IsReadOnly="True" Width="100">
<DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="HorizontalAlignment" Value="Center" />
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
<DataGridTextColumn x:Name="NumClaims" Binding="{Binding Path='NumClaims', Mode=OneTime}" IsReadOnly="True" Width="100">
<DataGridTextColumn.Header>
<StackPanel>
<TextBlock Text="Claims"/>
<TextBlock Text="{Binding Path=Data.TotalClaims, UpdateSourceTrigger=PropertyChanged, Source={StaticResource proxy}}" />
</StackPanel>
</DataGridTextColumn.Header>
<DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="HorizontalAlignment" Value="Center" />
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
<DataGridTextColumn x:Name="NewClaims" Binding="{Binding Path='NumNewClaims', Mode=OneTime}" IsReadOnly="True" Width="80">
<DataGridTextColumn.Header>
<StackPanel>
<TextBlock Text="New Claims"/>
<TextBlock Text="{Binding Path=Data.TotalNewClaims, UpdateSourceTrigger=PropertyChanged, Source={StaticResource proxy}}" />
</StackPanel>
</DataGridTextColumn.Header>
<DataGridTextColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Background" Value="{Binding NumNewClaims}"/>
</Style>
</DataGridTextColumn.CellStyle>
<DataGridTextColumn.ElementStyle>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="HorizontalAlignment" Value="Center" />
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
</TabItem>
</TabControl>
</StackPanel>
</Window>

How can I make a ComboBox in a DataGrid row unique?

Environment for the following question:
C#, WPF, XAML
How can I achieve to setup a table/a DataGrid with an undefined number of rows having a Combobox in an arbitrary column (number of columns is undefined as well)? (The other row's cells will be filled with the properties of the underyling object/entity.) The ComboBoxes shall all have the same items but the selected item shall be assigned to the underlying object of the row (of course). Hence, I think the ComboBox of each row must have a unique identifier.
The selected item shall be stored in a property of the underlying object/entity.
By the way:
The ComboBox shall be filled with items of a collection (List) that is not part of the row's underlying object/entity.
What would be the best way using WPF / XAML?
UPDATE (2018-12-14):
<Window x:Class="ConfigTool.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ConfigTool"
xmlns:lb="clr-namespace:ConfigTool.DataBinding"
mc:Ignorable="d"
Title="xxx" Height="650" Width="1200" Closing="CloseWindow">
<Window.Resources>
<CollectionViewSource x:Key="TagsCollectionViewSource" CollectionViewType="ListCollectionView"/>
<CollectionViewSource x:Key="NotificationsCollectionViewSource" CollectionViewType="ListCollectionView"/>
<CollectionViewSource x:Key="TagNamesCollectionViewSource" CollectionViewType="ListCollectionView"/>
<lb:StringListConverter x:Key="StringListConverter" />
</Window.Resources>
<Grid Margin="10,10,10,10">
<TabControl>
<TabItem Header="Tags">
<ScrollViewer HorizontalScrollBarVisibility="Auto">
<DataGrid x:Name="tagsGrid" DataContext="{StaticResource TagsCollectionViewSource}" ItemsSource="{Binding}"
AlternatingRowBackground="LightBlue" AutoGenerateColumns="False" CanUserAddRows="True" IsReadOnly="False"
SelectionMode="Single" BorderBrush="Magenta" BorderThickness="3">
<DataGrid.Columns>
<DataGridTextColumn x:Name="TagName" Header="Tag name" Binding="{Binding Mode=TwoWay, Path=TagName}"></DataGridTextColumn>
<DataGridTextColumn Header="Cycle" Binding="{Binding Mode=TwoWay, Path=Cycle}"></DataGridTextColumn>
<DataGridTextColumn Header="Source" Binding="{Binding Mode=TwoWay, Path=Source}"></DataGridTextColumn>
<DataGridTemplateColumn x:Name="editTagColumn" Header="Edit">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<WrapPanel>
<Button x:Name="btnTagDelete" Click="BtnTagDelete_Click" CommandParameter="{Binding}" Height="15" Width="15" Margin="2">
<Button.Content>
<Image Source="Resources/delete.png"></Image>
</Button.Content>
</Button>
</WrapPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</ScrollViewer>
</TabItem>
<TabItem Header="Notifications">
<ScrollViewer HorizontalScrollBarVisibility="Auto">
<DataGrid x:Name="notificationsGrid" DataContext="{StaticResource NotificationsCollectionViewSource}" ItemsSource="{Binding}"
AlternatingRowBackground="LightBlue" AutoGenerateColumns="False" CanUserAddRows="True" IsReadOnly="False"
SelectionMode="Single" BorderBrush="Magenta" BorderThickness="3">
<DataGrid.Columns>
<!--<DataGridTextColumn Header="Tag name" Binding="{Binding Mode=TwoWay, Path=TagName}"></DataGridTextColumn>-->
<DataGridTemplateColumn x:Name="tagNameColumn" Header="Tag name">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<!--<ItemContainerTemplate>
<StackPanel>-->
<!--DataContext="{Binding Source={StaticResource TagNamesCollectionViewSource}}">-->
<!--<ComboBox Width="200" DataContext="{StaticResource TagNamesCollectionViewSource}" ItemsSource="{Binding TagNames, Converter={StaticResource StringListConverter}}">-->
<ComboBox Name="notificationTagName" Width="200" DataContext="{StaticResource TagNamesCollectionViewSource}" ItemsSource="{Binding Source={StaticResource TagNamesCollectionViewSource}, RelativeSource={RelativeSource AncestorType=local:MainWindow}}"
SelectionChanged="notificationTagName_SelectionChanged" />
<!--<ComboBox Width="200" DataContext="{StaticResource TagNamesCollectionViewSource}" ItemsSource="{Binding Converter={StaticResource StringListConverter}}" />-->
<!--<ComboBox Width="200" ItemsSource="{Binding ElementName=Window2, Path=DataContext.TagNames, Converter={StaticResource StringListConverter}}" />-->
<!--<ComboBox HorizontalAlignment="Left" Margin="256,260,0,0" VerticalAlignment="Top" Width="120" x:Name="DataList" ItemsSource="{Binding DetailParams, Converter={StaticResource StringListConverter}}"/>-->
</DataTemplate>
<!--</StackPanel>
</ItemContainerTemplate>-->
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridCheckBoxColumn Header="IsActive" Binding="{Binding Mode=TwoWay, Path=IsActive}"></DataGridCheckBoxColumn>
<DataGridTextColumn Header="Type" Binding="{Binding Mode=TwoWay, Path=Type}"></DataGridTextColumn>
<DataGridTextColumn Header="Limit" Binding="{Binding Mode=TwoWay, Path=Limit}"></DataGridTextColumn>
<DataGridTextColumn Header="DetailTemplate" Binding="{Binding Mode=TwoWay, Path=DetailTemplate}"></DataGridTextColumn>
<!--<DataGridTextColumn Header="DetailParams" Binding="{Binding Mode=TwoWay, Path=DetailParams, Converter={StaticResource StringListConverter}}"></DataGridTextColumn>-->
<DataGridTemplateColumn x:Name="detailsParamColumn" Header="Edit">
<DataGridTemplateColumn.CellTemplate>
<ItemContainerTemplate>
<StackPanel> <!--DataContext="{Binding Source={StaticResource TagNamesCollectionViewSource}}">-->
<!--<ComboBox Width="200" DataContext="{StaticResource TagNamesCollectionViewSource}" ItemsSource="{Binding TagNames, Converter={StaticResource StringListConverter}}">-->
<ComboBox Width="200" DataContext="{StaticResource TagNamesCollectionViewSource}" ItemsSource="{Binding}" />
<!--<ComboBox Width="200" DataContext="{StaticResource TagNamesCollectionViewSource}" ItemsSource="{Binding Converter={StaticResource StringListConverter}}" />-->
<!--<ComboBox Width="200" ItemsSource="{Binding ElementName=Window2, Path=DataContext.TagNames, Converter={StaticResource StringListConverter}}" />-->
<!--<ComboBox HorizontalAlignment="Left" Margin="256,260,0,0" VerticalAlignment="Top" Width="120" x:Name="DataList" ItemsSource="{Binding DetailParams, Converter={StaticResource StringListConverter}}"/>-->
</StackPanel>
</ItemContainerTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="CauseProbability" Binding="{Binding Mode=TwoWay, Path=CauseProbability, Converter={StaticResource StringListConverter}}"></DataGridTextColumn>
<DataGridTemplateColumn x:Name="editNotificationsColumn" Header="Edit">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<WrapPanel>
<Button x:Name="btnNotificationDelete" Click="BtnNotificationDelete_Click" Height="15" Width="15" Margin="2">
<Image Source="Resources/delete.png"></Image>
</Button>
</WrapPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</ScrollViewer>
</TabItem>
</TabControl>
</Grid>
</Window>
It is happening because you are using the same collection for the Combo-Box in each row.
The ItemsSource for the Combo-Box should be a collection and it should be a member/property of class that set as DataContext for the DataGrid.
Or
Bind the SelectedItem property of Combo-Box to a member of your class.
See https://www.c-sharpcorner.com/uploadfile/dpatra/combobox-in-datagrid-in-wpf/

Unable to use MahApps style DataGrid within a UserControl

I'm pretty new to WPF, so I apologise in advance if the answer to this question is verysimple. I have looked around everywhere, but can't find an appropriate solution.
The low-down:
I have an application that is using MahApps. The Windows within my app work fine. I can set style and change themes, and it applies across all the windows.
The issue is that within my MainWindow I have a couple of UserControls. One of these UserControls has a DataGrid, and for some reason, the DataGrid will not take the default MahApps DataGrid style.
One other thing: My DataGrid uses DataTriggers to display different observable lists depending on a RadioButton that has been pressed. It therefore doesn't let me set the style of the DataGrid (as per the MahApps guide here: http://mahapps.com/controls/datagrid.html).
MahApps suggestion:
<DataGrid ItemsSource="{Binding People}" Margin="10,20,10,0"
AutoGenerateColumns="True"
Style="{StaticResource AzureDataGrid}">
Another suggestion I found was to add the MahApps resources to the Resource dictionary of my UserControl. That didn't work, so I removed that code.
My current UserControl xaml:
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:TrayportLibrary.Home"
xmlns:helpers="clr-namespace:TrayportLibrary.Helpers"
xmlns:controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
x:Class="TrayportLibrary.Search.SearchView"
mc:Ignorable="d" >
<UserControl.Resources>
<helpers:StringToVisibilityConverter x:Key="StringToVisibilityConverter"/>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</UserControl.Resources>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<ei:CallMethodAction TargetObject="{Binding}" MethodName="LoadCollections"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<StackPanel FocusManager.FocusedElement="{Binding ElementName=SearchBox}">
<Grid Name="MainGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBox x:Name="SearchBox"
Focusable="True"
VerticalAlignment="Center"
HorizontalAlignment="Right"
Text="{Binding SearchInput, UpdateSourceTrigger=PropertyChanged}"
Width="200"
Height="25"
BorderBrush="Black"
BorderThickness="2"
Grid.Column="0"
Grid.Row="0"
Margin="0,0,5,0"/>
<StackPanel Grid.Column="1"
Grid.Row="0"
Orientation="Horizontal"
VerticalAlignment="Center"
HorizontalAlignment="Left">
<RadioButton GroupName="SearchSelection"
Name="BookRadio"
Content="Books"
Margin="0,0,5,0"
IsChecked="{Binding SearchBook}"
Command="{Binding SetSearchCommand}"
CommandParameter="book"
Click="RadioButton_OnClick"/>
<RadioButton GroupName="SearchSelection"
Name="MemberRadio"
Content="Members"
IsChecked="{Binding SearchMember}"
Command="{Binding SetSearchCommand}"
CommandParameter="member"
Click="RadioButton_OnClick"/>
</StackPanel>
<FrameworkElement Grid.Row="1" Grid.Column="0" x:Name="Proxy"/>
<DataGrid Name="DataGrid"
Grid.Row="1"
Grid.ColumnSpan="2"
Grid.Column="0"
IsReadOnly="True"
AutoGenerateColumns="False"
Height="200"
VerticalScrollBarVisibility="Auto"
Visibility="{Binding Path=Text,
ElementName=SearchBox,
Converter={StaticResource
StringToVisibilityConverter}}">
<DataGrid.Columns>
<DataGridTextColumn Header="Book ID" Binding="{Binding BookID}" Visibility="{Binding DataContext.BookVisibility, Converter={StaticResource BooleanToVisibilityConverter}, Source={x:Reference Proxy}, Mode=TwoWay, NotifyOnSourceUpdated=True}"/>
<DataGridTextColumn Header="Title" Binding="{Binding Title}" Visibility="{Binding DataContext.BookVisibility, Converter={StaticResource BooleanToVisibilityConverter}, Source={x:Reference Proxy}, Mode=TwoWay, NotifyOnSourceUpdated=True}"/>
<DataGridTextColumn Header="Author(s)" Binding="{Binding AuthorData}" Visibility="{Binding DataContext.BookVisibility, Converter={StaticResource BooleanToVisibilityConverter}, Source={x:Reference Proxy}, Mode=TwoWay, NotifyOnSourceUpdated=True}"/>
<DataGridTextColumn Header="Date Due" Binding="{Binding DateDue, StringFormat=dd/MM/yyyy}" Visibility="{Binding DataContext.BookVisibility, Converter={StaticResource BooleanToVisibilityConverter}, Source={x:Reference Proxy}, Mode=TwoWay, NotifyOnSourceUpdated=True}"/>
<DataGridCheckBoxColumn Header="Out" Binding="{Binding IsOut}" Visibility="{Binding DataContext.BookVisibility, Converter={StaticResource BooleanToVisibilityConverter}, Source={x:Reference Proxy}, Mode=TwoWay, NotifyOnSourceUpdated=True}"/>
<DataGridTextColumn Header="On Loan to" Binding="{Binding OnLoanToUserName}" Visibility="{Binding DataContext.BookVisibility, Converter={StaticResource BooleanToVisibilityConverter}, Source={x:Reference Proxy}, Mode=TwoWay, NotifyOnSourceUpdated=True}"/>
<DataGridCheckBoxColumn Header="Lost" Binding="{Binding IsLost}" Visibility="{Binding DataContext.BookVisibility, Converter={StaticResource BooleanToVisibilityConverter}, Source={x:Reference Proxy}, Mode=TwoWay, NotifyOnSourceUpdated=True}"/>
<DataGridTextColumn Header="Name" Binding="{Binding Name}" Visibility="{Binding DataContext.MemberVisibility, Converter={StaticResource BooleanToVisibilityConverter}, Source={x:Reference Proxy}, Mode=TwoWay, NotifyOnSourceUpdated=True}"/>
<DataGridTextColumn Header="Username" Binding="{Binding UserName}" Visibility="{Binding DataContext.MemberVisibility, Converter={StaticResource BooleanToVisibilityConverter}, Source={x:Reference Proxy}, Mode=TwoWay, NotifyOnSourceUpdated=True}"/>
<DataGridTextColumn Header="Books on Loan" Binding="{Binding BooksOnLoan}" Visibility="{Binding DataContext.MemberVisibility, Converter={StaticResource BooleanToVisibilityConverter}, Source={x:Reference Proxy}, Mode=TwoWay, NotifyOnSourceUpdated=True}"/>
<DataGridTextColumn Header="Books Overdue" Binding="{Binding BooksOverdue}" Visibility="{Binding DataContext.MemberVisibility, Converter={StaticResource BooleanToVisibilityConverter}, Source={x:Reference Proxy}, Mode=TwoWay, NotifyOnSourceUpdated=True}"/>
</DataGrid.Columns>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<ei:CallMethodAction MethodName="OnSelectedItem" TargetObject="{Binding}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<DataGrid.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=MemberRadio, Path=IsChecked}" Value="true">
<Setter Property="DataGrid.ItemsSource" Value="{Binding Members}"/>
<Setter Property="DataGrid.SelectedItem" Value="{Binding SelectedMember}"/>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=BookRadio, Path=IsChecked}" Value="true">
<Setter Property="DataGrid.ItemsSource" Value="{Binding Books}"/>
<Setter Property="DataGrid.SelectedItem" Value="{Binding SelectedBook}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.Style>
</DataGrid>
</Grid>
</StackPanel>
Any advice/code/best practise would be greatly appreciated.
I'm also aware that my current xaml could probably be made simpler, but I just want to sort this issue first before I start refactoring.
Thanks in advance.
The problem is that you are overriding the style that would normally be applied to the DataGrid with your own custom style.
Your custom style can inherit setters from other styles by using the BasedOn attribute.
For example:
<Style BasedOn="{StaticResource AzureDataGrid}">
Or to inherit from the default style for the control type:
<Style BasedOn="{StaticResource {x:Type DataGrid}}">

problem with wpf datagrid selection + expander

I have an expander containing a datagrid with a rowdetailstemplate.
When I click on a datagrid row to see the row details template, the expander closes!
Anyone know why and how to fix this?
Update
Turns out that something else is happening:
The expanders are all contained in a TabItem. When I click on the grid row, TabControls.SelectionChanged fires (WHY!!!?!?!!?!?!?!) and then the data is recalculated and rebound.
So the real question is why does click a DataGrid row cause the Parent TabControl's SelectionChanged Event to fire? Here's the XAML:
<Window xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation" x:Class="BPPDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:BPPDemo"
Title="BPP Demo" Height="600" Width="700" Loaded="Window_Loaded">
<Window.Resources>
<local:AddrStatusColorConverter x:Key="addressStatusColorConverter"/>
<local:BoolToVisConverter x:Key="boolToVisConverter"/>
</Window.Resources>
<DockPanel>
<Menu DockPanel.Dock="Top">
<Menu.Items>
<MenuItem Header="File">
<MenuItem Header="Open Assessment" Command="{Binding SelectAssessmentCommand}"></MenuItem>
<MenuItem Header="Import Properties" Command="{Binding ImportPropertiesCommand}"></MenuItem>
</MenuItem>
<MenuItem Header="Properties" Visibility="{Binding IsSelected, ElementName=tabProperties,Converter={StaticResource boolToVisConverter}}">
<MenuItem Header="Delete All Properties" Command="{Binding DeleteAllPropertiesCommand}"></MenuItem>
<MenuItem Header="Resolve Invalid Addresses" Command="{Binding ValidateAddressesCommand}"></MenuItem>
<MenuItem Header="Select Situs" Command="{Binding SelectSitusCommand}"/>
</MenuItem>
</Menu.Items>
</Menu>
<DockPanel Margin="10">
<TextBlock Text="{Binding Assessment.Name}" FontWeight="Normal" FontSize="24" Foreground="#FF5C9EB7" DockPanel.Dock="Top" Margin="0,0,0,10"/>
<TabControl SelectionChanged="TabControl_SelectionChanged">
<TabItem x:Name="tabProperties" Header="Properties">
<DataGrid ItemsSource="{Binding Properties}" AutoGenerateColumns="False" IsReadOnly="True" SelectedItem="{Binding SelectedProperty,Mode=TwoWay}">
<DataGrid.Columns>
<DataGridTextColumn Header="Description" Binding="{Binding Description}"/>
<DataGridTextColumn Header="Cost" Binding="{Binding Cost,StringFormat='{}{0:c}'}"/>
<DataGridTextColumn Header="Year Acquired" Binding="{Binding YearAcquired}"/>
<DataGridTextColumn Header="Life In Years" Binding="{Binding LifeInYears}"/>
<DataGridTextColumn Header="Schedule" Binding="{Binding Schedule}"/>
<DataGridTextColumn Header="Current Value" Binding="{Binding CurrentValue,StringFormat='{}{0:c}'}" />
<DataGridTextColumn Header="Tax" Binding="{Binding Tax,StringFormat='{}{0:c}'}" />
<DataGridTemplateColumn Header="Address">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Address}" Foreground="{Binding AddressStatus, Converter={StaticResource addressStatusColorConverter}}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Address Status" Binding="{Binding AddressStatus}"/>
<DataGridTextColumn Header="Situs" Binding="{Binding Situs}"/>
</DataGrid.Columns>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<TextBlock>THIS ONE WORKS! WHY DOESN'T THE OTHER ONE????</TextBlock>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
</TabItem>
<TabItem Header="Listings" Name="tabListings">
<DataGrid x:Name="SitusGroups" AutoGenerateColumns="false" SelectionMode="Single" SelectionUnit="FullRow">
<DataGrid.Columns>
<DataGridTextColumn Header="Situs" Binding="{Binding Situs,StringFormat='{}{0:c}',TargetNullValue='none'}"></DataGridTextColumn>
<DataGridTextColumn Header="Cost" Binding="{Binding Cost,StringFormat='{}{0:c}'}"></DataGridTextColumn>
<DataGridTextColumn Header="Value" Binding="{Binding Value,StringFormat='{}{0:c}'}"></DataGridTextColumn>
<DataGridTextColumn Header="Tax" Binding="{Binding Tax,StringFormat='{}{0:c}'}"></DataGridTextColumn>
</DataGrid.Columns>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<TextBlock>I JUST WANT TO SEE THIS WHEN I CLICK ON A ROW!</TextBlock>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
</TabItem>
</TabControl>
</DockPanel>
</DockPanel>
The problem has to do with the way events are routed. TabControl and DataGrid derive from the same class, so when DataGrid SelectionChanged, my TabControl SelectionChanged handler was firing.
As the last comment at http://www.trentfguidry.net/post/2009/06/13/WPF-TabControl-SelectionChanged.aspx suggests, I checked the original source in my event handler and returned if the reference wasn't my tabcontrol.

Categories

Resources