checkbox checked event trigger multiple time wpf mvvm - c#

I got checkbox column in DataGrid that populating realtime download percentage in particular row, filtered by caseRefNo. i need to add checkbox changed event to perform some action. i used InvokeCommandAction to add the action to checkbox.
I realize that when i click the checkbox for the first time, It is ok and trigger only one time. but there are two times triggered when i click second time on the same checkbox.For third time clicking the same checkbox, it triggered four time. quite scary and difficult to figure it out.
here is my viewmodel code
public class DataGridDownloadViewModel:BindableBase
{
public ObservableCollection<tblTransaction> TransList { get; private set; }
public DispatcherTimer dispatchTimer = new DispatcherTimer();
public CollectionView TransView { get; private set; }
public DelegateCommand<object> CheckCommand { get; set; }
private String _UpdatePer;
public String UpdatePercentage
{
get { return _UpdatePer; }
set { SetProperty(ref _UpdatePer, value); }
}
private string _caseId;
public string CaseID
{
get { return _caseId; }
set { SetProperty(ref _caseId, value); }
}
private string _isChecked;
public string isChecked
{
get { return _isChecked; }
set { SetProperty(ref _isChecked, value); }
}
private bool CanExecute(object args)
{
return true;
}
private void CheckBoxChecker(object args)
{
//Should Work Here
// Totally not coming to this function
CheckBox chk = (CheckBox)args;
string thichintae = chk.Name.ToString();
Console.WriteLine(thichintae);
}
public DataGridDownloadViewModel(List<tblTransaction> model)
{
CheckCommand = new DelegateCommand<object>(CheckBoxChecker, CanExecute);
dispatchTimer.Interval = TimeSpan.FromMilliseconds(3000);
dispatchTimer.Tick += dispatchTimer_Tick;
BackGroundThread bgT = Application.Current.Resources["BackGroundThread"] as BackGroundThread;
bgT.GetPercentChanged += (ss, ee) =>
{
UpdatePercentage = bgT.local_percentage.ToString();
};
bgT.GetCaseID += (ss, ee) =>
{
CaseID = bgT.local_caseRef;
};
TransList =new ObservableCollection<tblTransaction>(model);
TransView = GetTransCollectionView(TransList);
TransView.Filter = OnFilterTrans;
var tokenSource = new CancellationTokenSource();
var token = tokenSource.Token;
var cancellationTokenSource = new CancellationTokenSource();
dispatchTimer.Start();
}
private void dispatchTimer_Tick(object sender, EventArgs e)
{
UpdateDataGrid();
}
public void UpdateDataGrid()
{
foreach (tblTransaction tran in TransList)
{
if (tran.caseRefNo == CaseID)
{
tran.incValue = int.Parse(UpdatePercentage);
}
else
{
tran.incValue = tran.incValue;
}
}
TransView.Refresh();
}
bool OnFilterTrans(object item)
{
var trans = (tblTransaction)item;
return true;
}
public CollectionView GetTransCollectionView(ObservableCollection<tblTransaction> tranList)
{
return (CollectionView)CollectionViewSource.GetDefaultView(tranList);
}
}
this is XAML for above view model.
<Window x:Class="EmployeeManager.View.DataGridDownload"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
Title="DataGridDownload" Height="600" Width="790">
<Grid>
<DataGrid HorizontalAlignment="Left" ItemsSource="{Binding TransView}" AutoGenerateColumns="False" Margin="10,62,0,0" VerticalAlignment="Top" Height="497" Width="762">
<DataGrid.Columns>
<DataGridTextColumn Header="caseRefNo" Binding="{Binding caseRefNo}" />
<DataGridTextColumn Header="subjMatr" Binding="{Binding subjMatr}" />
<DataGridTextColumn Header="Download %" Binding="{Binding incValue}" />
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox Name="abcdef"
Content="Please Select" IsChecked="{Binding Path=IsSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Checked">
<i:InvokeCommandAction CommandParameter="{Binding ElementName=abcdef}" Command="{Binding DataContext.CheckCommand, RelativeSource={RelativeSource FindAncestor, AncestorType=DataGrid}}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</CheckBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label Content="{Binding incValue,UpdateSourceTrigger=PropertyChanged}" Background="Red" Foreground="White" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
<Label Content="{Binding UpdatePercentage}" HorizontalAlignment="Left" Background="Blue" Foreground="White" Margin="10,10,0,0" VerticalAlignment="Top" Width="338" Height="30">
</Label>
<Button Content="Button" HorizontalAlignment="Left" Margin="672,20,0,0" VerticalAlignment="Top" Width="75"/>
</Grid>
</Window>
Here is my model
public class tblTransaction
{
public string caseRefNo { get;set;}
public string subjMatr { get; set; }
public int incValue { get; set; }
public DateTime? longTime { get; set; }
public bool IsSelected { get; set; }
}
This is picture of my form
Is it because of DispatcherTimer ? All suggestion are welcome.
df

I think I left a comment in your previous question saying that wrapping your collection to CollectionView is quite smelly.
Anyway, the TransView.Refresh(); is causing the problem in your code.
TransView.Refresh will trigger the "Checked" event for each checked checkbox. The refresh basically asking the wpf engine re-populate all the data to your CollectionView and in turn, each checked checkbox will fire the checked event all over again.
Try setting dispatchTimer.Interval to a much shorter time e.g. 300. You should be able to see the "tick" in checkbox keep flicking becoz of the TransView.Refresh.
For real, I have no idea why you don't just bind your TransList to your DataGrid and called BeginInvoke on UpdateDataGrid method.
To demo how ObservableCollection works
I used the ObservableCollection to re-wrote some part of your code. At least make things better fall in line with MVVM model.
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public class MainViewModel : ViewModelBase
{
public ObservableCollection<TblTransaction> TransList { get; private set; }
public DispatcherTimer DispatchTimer = new DispatcherTimer();
public MainViewModel()
{
var model = new ObservableCollection<TblTransaction>();
for (int i = 0; i < 5; i++)
{
model.Add(new TblTransaction { CaseRefNo = i.ToString(), IncValue = i, LongTime = DateTime.Now, SubjMatr = i.ToString() });
if (i == 3)
model[i].IsSelected = true;
}
DispatchTimer.Interval = TimeSpan.FromMilliseconds(200);
DispatchTimer.Tick += dispatchTimer_Tick;
TransList = model;
DispatchTimer.Start();
}
private void dispatchTimer_Tick(object sender, EventArgs e)
{
UpdateDataGrid();
}
public void UpdateDataGrid()
{
var ran = new Random();
foreach (var tran in TransList)
tran.IncValue = ran.Next(0, 100);
}
}
public class TblTransaction : ViewModelBase
{
private string caseRefNo;
private string subjMatr;
private int incValue;
private DateTime? longTime;
private bool isSelected;
public DelegateCommand<object> CheckCommand { get; set; }
public TblTransaction()
{
CheckCommand = new DelegateCommand<object>(CheckBoxChecker, (p) => true);
}
private void CheckBoxChecker(object args)
{
//Should Work Here
// Totally not coming to this function
//CheckBox chk = (CheckBox)args;
//string thichintae = chk.Name;
Console.WriteLine(args);
}
public string CaseRefNo
{
get { return caseRefNo; }
set
{
caseRefNo = value;
OnPropertyChanged();
}
}
public string SubjMatr
{
get { return subjMatr; }
set
{
subjMatr = value;
OnPropertyChanged();
}
}
public int IncValue
{
get { return incValue; }
set
{
incValue = value;
OnPropertyChanged();
}
}
public DateTime? LongTime
{
get { return longTime; }
set
{
longTime = value;
OnPropertyChanged();
}
}
public bool IsSelected
{
get { return isSelected; }
set
{
isSelected = value;
OnPropertyChanged();
}
}
}
<Window x:Class="WpfTestProj.MainWindow"
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:WpfTestProj"
xmlns:interact="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=local:MainViewModel, IsDesignTimeCreatable=False}"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DataGrid HorizontalAlignment="Left" ItemsSource="{Binding TransList}" AutoGenerateColumns="False" Margin="10,62,0,0" VerticalAlignment="Top" Height="497" Width="762">
<DataGrid.Columns>
<DataGridTextColumn Header="caseRefNo" Binding="{Binding CaseRefNo}" />
<DataGridTextColumn Header="subjMatr" Binding="{Binding SubjMatr}" />
<DataGridTextColumn Header="Download %" Binding="{Binding IncValue}" />
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox
Content="Please Select" IsChecked="{Binding Path=IsSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<interact:Interaction.Triggers>
<interact:EventTrigger EventName="Checked">
<interact:InvokeCommandAction CommandParameter="{Binding Path=CaseRefNo}" Command="{Binding Path=CheckCommand}" />
</interact:EventTrigger>
</interact:Interaction.Triggers>
</CheckBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label Content="{Binding IncValue, UpdateSourceTrigger=PropertyChanged}" Background="Red" Foreground="White" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
<Button Content="Button" HorizontalAlignment="Left" Margin="672,20,0,0" VerticalAlignment="Top" Width="75"/>
</Grid>

Related

How to shift focus from an edited cell in a datagrid to a text box in WPF

I'm attempting to have a user input textbox take an ID string and fetch data to fill rows in a datagrid, then trigger editing a specific row and cell in the datagrid based on the value of the user input and then put focus back on the textbox when the return/enter key is pressed after the user enters a value in the datagrid cell.
I have most of this working correctly except for the last step, the enter key has to be pressed twice in order to return to the text box, I would like it to return on first press.
If the edited cell is selected by the user directly using the mouse then it works correctly, a single enter press sends focus back to the textbox.
The automatic cell editing is triggered with an attached property and a helper class that listens for the OnCurrentCellChanged event and triggers the datagrid BeginEdit method.
I wonder if this needs to be closed off/ended before the focus can change properly?
(Helper class implemented based on answer here, with great thanks to #Orace)
How can I achieve this? I have tried commiting the edit, cancelling the edit in the xaml code behind PreviewKeyDown method but no luck. So possibly I have to change the OnCurrentCellChanged event method somehow?
my xaml:
<Window x:Class="TestChangingEditedCellFocus.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:TestChangingEditedCellFocus" d:DataContext="{d:DesignInstance Type=local:ViewModel}"
mc:Ignorable="d"
FocusManager.FocusedElement="{Binding ElementName=idfield}"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<ResourceDictionary>
<CollectionViewSource x:Key="srModels" Source="{Binding Models}"/>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal">
<TextBox x:Name="idfield" Width="100" Height="30" Text="{Binding Path=ModelId, UpdateSourceTrigger=PropertyChanged}"/>
<Button IsDefault="True" Command="{Binding Path=Command}" Content="Get Row" Height="30"/>
</StackPanel>
<DataGrid Grid.Row="1"
x:Name="modelgrid"
local:DataGridAutoEdit.AutoEditColumn="2"
ItemsSource="{Binding Source={StaticResource srModels}}"
SelectedItem="{Binding CurrentModel, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}"
AutoGenerateColumns="False"
SelectionMode="Single"
SelectionUnit="FullRow"
PreviewKeyDown="modelgrid_PreviewKeyDown"
>
<DataGrid.Columns>
<DataGridTemplateColumn Header="ID" Width="Auto" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label Content="{Binding Id}" HorizontalContentAlignment="Right"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Name" Width="Auto" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Label Content="{Binding Name}" HorizontalContentAlignment="Right"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Value" Width="Auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" BorderThickness="0"
VerticalContentAlignment="Center" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" HorizontalContentAlignment="Right"
FocusManager.FocusedElement="{Binding RelativeSource={RelativeSource Self}}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
Xaml code behind:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new ViewModel();
}
private void modelgrid_PreviewKeyDown(object sender, KeyEventArgs e)
{
if ((e.Key == Key.Enter) || (e.Key == Key.Return))
{
//DataGrid grid = sender as DataGrid;
//grid.CancelEdit();
idfield.Focus();
idfield.SelectAll();
}
}
}
The VeiwModel:
public class ViewModel : ObservableObject
{
private ObservableCollection<model> _models;
private model _currentModel;
private string _modelId;
private ICommand _command;
public ObservableCollection<model> Models
{
get
{
if (_models is null)
{
_models = new ObservableCollection<model>();
OnPropertyChanged("Models");
}
return _models;
}
}
public model CurrentModel
{
get
{
return _currentModel;
}
set
{
_currentModel = value;
OnPropertyChanged("CurrentModel");
}
}
public string ModelId
{
get
{
return _modelId;
}
set
{
_modelId = value;
OnPropertyChanged("ModelId");
}
}
public ICommand Command
{
get
{
if (_command == null)
{
_command = new RelayCommand(param=>ExcecuteCommand(), pred=> ModelId is not null);
}
return _command;
}
}
public void ExcecuteCommand()
{
Models.Clear();
if (Models.Count == 0)
{
Models.Add(new model() { Id = 1, Name = "name1" });
Models.Add(new model() { Id = 2, Name = "name2" });
Models.Add(new model() { Id = 3, Name = "name3" });
Models.Add(new model() { Id = 4, Name = "name4" });
}
foreach (model model in Models)
{
System.Diagnostics.Debug.WriteLine("Model: " + model.Name);
int id = int.Parse(ModelId);
if(id == model.Id)
{
CurrentModel = model;
}
}
ModelId = null;
}
}
The DataGridAutoEdit helper class to trigger edit mode:
class DataGridAutoEdit
{
public static readonly DependencyProperty AutoEditColumnProperty = DependencyProperty.RegisterAttached("AutoEditColumn", typeof(int), typeof(DataGridAutoEdit), new PropertyMetadata(default(int), AutoEditColumnChangedCallback));
public static void SetAutoEditColumn(DependencyObject element, int value)
{
element.SetValue(AutoEditColumnProperty, value);
}
public static int GetAutoEditColumn(DependencyObject element)
{
return (int)element.GetValue(AutoEditColumnProperty);
}
private static void AutoEditColumnChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is not DataGrid dataGrid)
return;
GetAutoEditColumnHelper(dataGrid)?.Dispose();
if (e.NewValue is int columnIndex)
{
SetAutoEditColumnHelper(d, new AutoEditColumnHelper(dataGrid, columnIndex));
}
else
{
d.ClearValue(AutoEditColumnHelperProperty);
}
}
private static readonly DependencyProperty AutoEditColumnHelperProperty = DependencyProperty.RegisterAttached("AutoEditColumnHelper", typeof(AutoEditColumnHelper), typeof(DataGridAutoEdit), new PropertyMetadata(default(AutoEditColumnHelper)));
private static void SetAutoEditColumnHelper(DependencyObject element, AutoEditColumnHelper value)
{
element.SetValue(AutoEditColumnHelperProperty, value);
}
private static AutoEditColumnHelper? GetAutoEditColumnHelper(DependencyObject element)
{
return element.GetValue(AutoEditColumnHelperProperty) as AutoEditColumnHelper;
}
//add private class to get datagrid auto cel edit function working, move to helpers if this works
private class AutoEditColumnHelper : IDisposable
{
private readonly DataGrid _dataGrid;
private readonly int _columnIndex;
private object? _lastItem;
public AutoEditColumnHelper(DataGrid dataGrid, int columnIndex)
{
_dataGrid = dataGrid;
_columnIndex = columnIndex;
_dataGrid.CurrentCellChanged += OnCurrentCellChanged;
}
public void Dispose()
{
_dataGrid.CurrentCellChanged -= OnCurrentCellChanged;
}
private void OnCurrentCellChanged(object? sender, EventArgs e)
{
DataGridCellInfo currentCell = _dataGrid.CurrentCell;
if (!currentCell.IsValid || Equals(currentCell.Item, _lastItem))
{
return;
}
DataGridColumn autoEditColumn = GetAutoEditColumn();
if (autoEditColumn is null)
{
return;
}
_dataGrid.Dispatcher.BeginInvoke(() =>
{
_lastItem = _dataGrid.SelectedItem;
_dataGrid.CurrentCell = new DataGridCellInfo(_lastItem, autoEditColumn);
_dataGrid.BeginEdit();
});
}
private DataGridColumn? GetAutoEditColumn()
{
return _columnIndex < 0 || _columnIndex > _dataGrid.Columns.Count ? null : _dataGrid.Columns[_columnIndex];
}
}
}
A working simplified project is here.
After some trial and error I found editing my PreviewKeyDowan method in code behind to both Commit and Cancel the edit AND using SendKeys to send the Enter command again worked to send the cursor back to the textbox feild as I wanted:
private void modelgrid_PreviewKeyDown(object sender, KeyEventArgs e)
{
if ((e.Key == Key.Enter) || (e.Key == Key.Return))
{
DataGrid grid = sender as DataGrid;
grid.CommitEdit();
grid.CancelEdit();
SendKeys.SendWait("{ENTER}");
idfield.Focus();
}
}
but this seems pretty hacky and I'll be happy for any other suggestions.

How to properly bind Checkbox property

I am working on a wpf application and I am dealing with checkboxes now
The problem when I set the Ischecked property to "True" like this:
<CheckBox Visibility="{Binding checkVisibility}" IsChecked="true"
IsEnabled="True"></CheckBox>
I get my checkbox checked
But when I try to bind a booléan property that it's value is "true" i get my checkbox always unchecked
I can't see where is the proplem
this is my xaml
<CheckBox Visibility="{Binding checkVisibility}" IsChecked="{Binding Path=test,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" IsEnabled="True"></CheckBox>
this is my property
public bool _test = true;
public bool test {
get {
return _test;
}
set {
if (_test == value) {
return;
}
_test = value;
RaisePropertyChanged("test");
}
}
I want my checkbox to reflect my property value and vice versa but it's not the case as my checkbox is always unchecked
I am missing something?
Edit
Here is my VM:
namespace X{
public class MyViewModel :
{
public MyViewModel()
{
TestCheckbox();
}
#Region Properties
public bool _test1 = true;
public bool test1
{
get
{
return _test1;
}
set
{
if (_test1 == value)
{
return;
}
_test1 = value;
RaisePropertyChanged("test1");
}
}
ObservableCollection<Output> _output_List;
public ObservableCollection<Output> output_List
{
get { return _output_List; }
set
{
if (_output_List == value) return;
_output_List = value;
RaisePropertyChanged("output_List");
}
}
#EndRegion
#Region ButtonCommand
private RelayCommand _SetOutputPropertiesCommand;
public RelayCommand SetOutputPropertiesCommand => _SetOutputPropertiesCommand
?? (_SetOutputPropertiesCommand = new RelayCommand(
() =>
{
foreach (Output item in output_List)
{
item.myvalue=Test2;
}
}
}));
#EndRegion
#Region Method
public void TestCheckbox()
{
Console.Writeline(Test2);
}
#EndRegion
}
public class Output
{
public string label { get; set; }
public string type { get; set; }
public bool myvalue { get; set; }
public bool Test2 { get; set; }
[System.ComponentModel.DataAnnotations.Schema.NotMapped]
[JsonIgnore]
public string checkVisibility { get; set; }
}
}
My Xaml : my checkboxes are integrated in a DataGrid view
<DataGrid x:Name ="GridO" Style="{x:Null}"
ItemsSource= "{Binding output_List,UpdateSourceTrigger=PropertyChanged}"
AutoGenerateColumns="False" CellStyle="{StaticResource Body_Content_DataGrid_Centering}"
Margin="5,0" IsReadOnly="True" SelectionMode="Single" RowHeight="50" Height="Auto">
<DataGrid.Columns>
<DataGridTextColumn Width="40*" Binding="{Binding label}">
<DataGridTextColumn.HeaderTemplate>
<DataTemplate>
<TextBlock Text="Input"></TextBlock>
</DataTemplate>
</DataGridTextColumn.HeaderTemplate>
</DataGridTextColumn>
<DataGridTextColumn Width="40*" Binding="{Binding type}">
<DataGridTextColumn.HeaderTemplate>
<DataTemplate>
<TextBlock Text = "Type"></TextBlock>
</DataTemplate>
</DataGridTextColumn.HeaderTemplate>
</DataGridTextColumn>
<DataGridTemplateColumn Width="20*" >
<DataGridTemplateColumn.Header>
<TextBlock Text="Value" />
</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox Margin="20,0,0,0" Visibility="{Binding checkVisibility }" IsChecked="{Binding Test2,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" IsEnabled="True"></CheckBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
<Button x:Name="Valid_output" Cursor="Hand" Background="Transparent" Height="55" Width="140" Margin="0,0,20,0" Command="{Binding SetOutputPropertiesCommand}" >
The bind is Working with "Test2" and not working with "Test1" which not in the same class as Test2
NB: the Button command(which is in the same class as "Test1") is working well
My DataTemplate: are in the App.xaml
xmlns:v="clr-namespace:X.View"
xmlns:vm="clr-namespace:X"
<DataTemplate DataType="{x:Type vm:MyViewModel}">
<v:MyWindow/>
I see the main problem in the DataGrid. You set ItemsSource to a collection, so for every row in the DataGrid the data source is one item in that collection. Not your MyViewModel.
This is the reason, why the Test2 is working - it is in the class which instances are in the collection.
You could try to add CheckBox to the window without DataGrid and bind the Test1 - it should work.
If you really want to use some property from your MyViewModel, you can, but it is not that easy. You have to have there something like:
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:YourNamespace"
<!--...something...-->
<DataGrid.Resources>
<local:BindingProxy x:Key="Proxy" Data="{Binding}" />
</DataGrid.Resources>
<!--...something...-->
And then your binding in the DataGrid will look like this:
IsChecked="{Binding Data.Test1, Source={StaticResource Proxy}}"
Of course I don't know the exact settings of your application so you will have to complete/change the code according to them.
I suggest you to add a ViewModelBase class, like that
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName =
null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Extends your ViewModel with this ViewModelBase class and implements your property
private bool myProperty;
public bool MyProperty { get; set; OnPropertyChanged(); }
Then you just have to bind on your property
<CheckBox IsChecked="{Binding MyProperty}"></CheckBox>
EDIT: To set your ViewModel as DataContext for your View you can set it from the code
MyView.DataContext = new MyViewModel();
or from the view, in the Window/User Control
<Window x:Class="MyApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyApplication"
Title="MainWindow" Height="350" Width="525"
DataContext="local.MyViewModel">

How to Select All CheckBox of a Column on DataGrid Header CheckBox in WPF DataGrid

Im facing an issue with WPF DataGrid Checkboxes C#.
Im not finding a way to select all cell template checkboxes when the header template checkbox is selected. in viewmodel its working fine. it get select all but in view it no showing any selected checkbox sign/mark on checked header checkbox.The problem I'm stuck with is related to checkbox in DataGrid(WPF)
click this link I want to do same like this
My XAML code :
<DataGrid x:Name="DgLines" ItemsSource="{Binding OpcUaEndpoints}"
MouseDoubleClick="DgLines_MouseDoubleClick" SelectionMode="Extended"
DataContext="{Binding}" IsReadOnly="True" Grid.ColumnSpan="5">
<DataGrid.Columns>
<DataGridTemplateColumn
<DataGridTemplateColumn.HeaderTemplate>
<DataTemplate>
<CheckBox Name="ckbSelectedAll" Checked="ckbSelectedAll_Checked" Unchecked="ckbSelectedAll_Unchecked"
IsChecked="{Binding IsSelected, UpdateSourceTrigger=PropertyChanged}"></CheckBox>
</DataTemplate>
</DataGridTemplateColumn.HeaderTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox Name="cbkSelect" Checked="cbkSelect_Checked" Unchecked="cbkSelect_Unchecked"
IsChecked="{Binding IsSelected, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<!--<DataGridTextColumn Width="200" Header="Id" Binding="{Binding Id }" />-->
<DataGridTextColumn Width="200" Header="Name" Binding="{Binding Name}"/>
<DataGridTextColumn Width="500" Header="Description" Binding="{Binding Description}"/>
<DataGridTextColumn Width="500" Header="Lines" Binding="{Binding Endpoint}"/>
</DataGrid.Columns>
</DataGrid>
ViewModelCode:
private void ckbSelectedAll_Unchecked(object sender, RoutedEventArgs e)
{
// this.DgLines.UnselectAll();
foreach (AddLinesViewModel c in DgLines.ItemsSource)
{
c.IsSelected = false;
}
}
private static OpcUaEndpointsListViewModel _instance;
private static readonly object Padlock = new object();
private ICommand _addCommand;
private ICommand _uncheckCommand;
private ICommand _searchcommand;
private ObservableCollection<AddOpcUaEndpointsViewModel> _endpoint;
public string _charNameFromTB;
public OpcUaEndpointsListViewModel()
{
BindDataGrid();
}
public static OpcUaEndpointsListViewModel Instance
{
get
{
lock (Padlock)
{
return _instance ?? (_instance = new OpcUaEndpointsListViewModel());
}
}
}
/// <summary>
/// //OPC UA Endpoint List
/// </summary>
public ObservableCollection<AddOpcUaEndpointsViewModel> OpcUaEndpoints
{
get => _endpoint;
set
{
if (OpcUaEndpoints == value)
{
_endpoint = value;
OnPropertyChanged("OpcUaEndpoints");
}
}
}
public string CharNameFromTB
{
get { return _charNameFromTB; }
set
{
_charNameFromTB = value;
OnPropertyChanged("CharNameFromTB");
}
}
public ICommand AddCommand
{
get { return _addCommand ?? (_addCommand = new RelayCommand(p => ExecuteAddCommand())); }
}
public ICommand SearchCommand
{
get { return _searchcommand ?? (_searchcommand = new RelayCommand(p => ExecuteSearchCommand())); }
}
private void ExecuteSearchCommand()
{
BindDataGridsearch();
}
private void BindDataGrid()
{
var opcendptsModel = opcUaEndpointsService.GetAll();
_endpoint = new ObservableCollection<AddOpcUaEndpointsViewModel>(opcendptsModel.Select(p => new AddOpcUaEndpointsViewModel(p)));
}
Please find working code. I have made some modification to your code
XAML
<DataGrid x:Name="DgLines" ItemsSource="{Binding OpcUaEndpoints}" AutoGenerateColumns="False"
SelectionMode="Extended" IsReadOnly="True" Grid.ColumnSpan="5">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.HeaderTemplate>
<DataTemplate>
<CheckBox Name="ckbSelectedAll"
IsChecked="{Binding IsSelected, UpdateSourceTrigger=PropertyChanged}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Checked" >
<i:InvokeCommandAction Command="{Binding DataContext.CheckedCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}" />
</i:EventTrigger>
<i:EventTrigger EventName="Unchecked" >
<i:InvokeCommandAction Command="{Binding DataContext.UncheckedCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</CheckBox>
</DataTemplate>
</DataGridTemplateColumn.HeaderTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox Name="cbkSelect"
IsChecked="{Binding IsSelected, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<!--<DataGridTextColumn Width="200" Header="Id" Binding="{Binding Id }" />-->
<DataGridTextColumn Width="200" Header="Name" Binding="{Binding Name}"/>
<DataGridTextColumn Width="500" Header="Description" Binding="{Binding Description}"/>
<DataGridTextColumn Width="500" Header="Lines" Binding="{Binding Endpoint}"/>
</DataGrid.Columns>
</DataGrid>
c#
public class OpcUaEndpointsListViewModel : INotifyPropertyChanged
{
private static OpcUaEndpointsListViewModel _instance;
private static readonly object Padlock = new object();
private ICommand _addCommand;
//private ICommand _uncheckCommand;
private ICommand _searchcommand;
private ICommand _checkedCommand { get; set; }
private ICommand _unCheckedCommand { get; set; }
private ObservableCollection<AddOpcUaEndpointsViewModel> _endpoint;
public string _charNameFromTB;
public event PropertyChangedEventHandler PropertyChanged;
public OpcUaEndpointsListViewModel()
{
BindDataGrid();
}
public static OpcUaEndpointsListViewModel Instance
{
get
{
lock (Padlock)
{
return _instance ?? (_instance = new OpcUaEndpointsListViewModel());
}
}
}
/// <summary>
/// //OPC UA Endpoint List
/// </summary>
public ObservableCollection<AddOpcUaEndpointsViewModel> OpcUaEndpoints
{
get { return _endpoint; }
set
{
if (OpcUaEndpoints == value)
{
_endpoint = value;
OnPropertyChanged("OpcUaEndpoints");
}
}
}
public string CharNameFromTB
{
get { return _charNameFromTB; }
set
{
_charNameFromTB = value;
OnPropertyChanged("CharNameFromTB");
}
}
public ICommand AddCommand
{
get { return _addCommand ?? (_addCommand = new WpfApplication1.RelayCommand<object>(p => ExecuteAddCommand())); }
}
public ICommand SearchCommand
{
get { return _searchcommand ?? (_searchcommand = new RelayCommand<object>(p => ExecuteSearchCommand())); }
}
public ICommand CheckedCommand
{
get { return _checkedCommand ?? (_checkedCommand = new WpfApplication1.RelayCommand<object>(p => ExecuteCheckedCommand())); }
}
public ICommand UncheckedCommand
{
get { return _unCheckedCommand ?? (_unCheckedCommand = new WpfApplication1.RelayCommand<object>(p => ExecuteUnCheckedCommand())); }
}
private void ExecuteSearchCommand()
{
///BindDataGridsearch();
}
private void ExecuteCheckedCommand()
{
foreach (var item in _endpoint)
{
item.IsSelected = true;
}
}
private void ExecuteUnCheckedCommand()
{
foreach (var item in _endpoint)
{
item.IsSelected = false;
}
}
private void ExecuteAddCommand()
{
///BindDataGridsearch();
}
private void BindDataGrid()
{
_endpoint = new ObservableCollection<AddOpcUaEndpointsViewModel>();
_endpoint.Add(new AddOpcUaEndpointsViewModel { Name = "A", Description = "A", Endpoint = 1 });
_endpoint.Add(new AddOpcUaEndpointsViewModel { Name = "B", Description = "B", Endpoint = 2 });
_endpoint.Add(new AddOpcUaEndpointsViewModel { Name = "C", Description = "C", Endpoint = 3 });
_endpoint.Add(new AddOpcUaEndpointsViewModel { Name = "D", Description = "D", Endpoint = 4 });
_endpoint.Add(new AddOpcUaEndpointsViewModel { Name = "E", Description = "E", Endpoint = 5 });
}
public void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class AddOpcUaEndpointsViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private string _name;
public string Name
{
get { return _name; }
set { _name = value; OnPropertyChanged("Name"); }
}
private string _description;
public string Description
{
get { return _description; }
set { _description = value; OnPropertyChanged("Description"); }
}
private int _endPoint;
public int Endpoint
{
get { return _endPoint; }
set { _endPoint = value; OnPropertyChanged("Endpoint"); }
}
private bool _isSelected;
public bool IsSelected
{
get { return _isSelected; }
set { _isSelected = value; OnPropertyChanged("IsSelected"); }
}
}
The DataGrid column definitions do not inherit the DataContext as they're not part of the visual tree.
You will have to use a BindingProxy¹ to get around this.
<DataGrid.Resources>
<attached:BindingProxy x:Key="proxy" Data="{Binding}"/>
</DataGrid.Resources>
<DataGridTemplateColumn>
<DataGridTemplateColumn.Header>
<CheckBox IsChecked="{Binding Data.IsHeaderCheckBoxChecked, Source={StaticResource proxy}}"/>
</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsSelected, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
BindingProxy
public class BindingProxy : Freezable
{
#region XAML Properties
public static readonly DependencyProperty DataProperty =
DependencyProperty.Register(nameof(Data), typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
public object Data
{
get { return GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
#endregion
#region Freezable
protected override Freezable CreateInstanceCore()
{
return new BindingProxy();
}
#endregion
}
Also remember that there are no UI-controls in your VM and no XXX_Clicked handler or smiliar. These belong in the code-behind file (*.xaml.cs), if necessary.
¹ You may also check this question.

Updating ComboBox in XAML without Somegrid.Items.Refresh()

I'm new in WPF+C# and starting to get a grip on it.
I want to update ComboBox inside DataGrid when program is running.
Unfortunately, ComboBox never show any selected item if I'm using Somegrid.Item.Refresh() to update DataGrid.
Here is the XAML
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DataGrid Name="Somegrid" HorizontalAlignment="Left" AutoGenerateColumns="False" CanUserAddRows="False" CanUserDeleteRows="False">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.Header>
<TextBlock Text="SomebodY" />
</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Somebody}" SelectionChanged="ComboBox_SelectionChanged_Somebody" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.Header>
<TextBlock Text="SomethinG" />
</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Something}" SelectionChanged="ComboBox_SelectionChanged_Something" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.Header>
<TextBlock Text="SomewherE" />
</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Somewhere}" SelectionChanged="ComboBox_SelectionChanged_Somewhere" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
Behind code
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
someclassFoo.Somebody = new List<string>() { "Alan", "Benjamin" };
observableSomeclassFoo.Add(someclassFoo);
Somegrid.ItemsSource = observableSomeclassFoo;
}
public SomeclassFoo someclassFoo = new SomeclassFoo();
private ObservableCollection<SomeclassFoo> _observableSomeclassFoo = new ObservableCollection<SomeclassFoo>();
public ObservableCollection<SomeclassFoo> observableSomeclassFoo { get { return _observableSomeclassFoo; } }
private void ComboBox_SelectionChanged_Somebody(object sender, RoutedEventArgs e)
{
System.Windows.Controls.ComboBox cb1 = (System.Windows.Controls.ComboBox)sender;
if (cb1.SelectedItem.ToString() == "Alan")
{
someclassFoo.Something = new List<string>() { "Apple" };
}
else if (cb1.SelectedItem.ToString() == "Benjamin")
{
someclassFoo.Something = new List<string>() { "Banana" };
}
//Somegrid.Items.Refresh();
}
private void ComboBox_SelectionChanged_Something(object sender, RoutedEventArgs e)
{
System.Windows.Controls.ComboBox cb2 = (System.Windows.Controls.ComboBox)sender;
if (cb2.SelectedItem.ToString() == "Apple")
{
someclassFoo.Somewhere = new List<string>() { "Antartica" };
}
else if (cb2.SelectedItem.ToString() == "Banana")
{
someclassFoo.Somewhere = new List<string>() { "Bedrock" };
}
//Somegrid.Items.Refresh();
}
private void ComboBox_SelectionChanged_Somewhere(object sender, RoutedEventArgs e)
{
System.Windows.Controls.ComboBox cb3 = (System.Windows.Controls.ComboBox)sender;
MessageBox.Show(cb3.SelectedItem.ToString().ToUpper() + " selected");
}
}
}
Another class
using System.Collections.Generic;
namespace WpfApplication1
{
public class SomeclassFoo
{
public IList<string> Somebody { get; set; }
public IList<string> Something { get; set; }
public IList<string> Somewhere { get; set; }
}
}
How I can update the ComboBox SomethinG and ComboBox SomewherE without using Somegrid.Item.Refresh() ?
The SomeclassFoo type should implement the INotifyPropertyChanged interface and raise change notifications:
public class SomeclassFoo : INotifyPropertyChanged
{
private IList<string> _somebody;
public IList<string> Somebody
{
get { return _somebody; }
set { _somebody = value; NotifyPropertyChanged(); }
}
private IList<string> _something;
public IList<string> Something
{
get { return _something; }
set { _something = value; NotifyPropertyChanged(); }
}
private IList<string> _someWhere;
public IList<string> Somewhere
{
get { return _someWhere; }
set { _someWhere = value; NotifyPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
How to: Implement Property Change Notification: https://msdn.microsoft.com/en-us/library/ms743695(v=vs.110).aspx
Instead of refreshing the grid, remove the current source and set a new source:
yourGrid.ItemsSource = null;
yourGrid.ItemsSource = yourDataSource;

when click dataGridview column Visiblity change of a textbox in WPF-MVVM?

I want to make a text Box Visible when clicking a DataGrid Column. I use this text box for description of a data Grid column
My two column has grid view (Item and Amount columns)
<DataGrid>
<DataGrid.Columns>
<DataGridTemplateColumn Header="Item" Width="*">
<DataGridTemplateColumn.CellTemplate>
<TextBlock Text="{Binding Item}" VerticalAlignment="Center"/>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
<DataGrid.Columns>
<DataGridTemplateColumn Header="Amount" Width="*">
<DataGridTemplateColumn.CellTemplate>
<TextBlock Text="{Binding Amount}" VerticalAlignment="Center"/>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
I want get the sum of Column [Amount] and show it on a textbox, that is visible only when I click [Amount] Column
Please try the next code:
1. Xaml:
<Window x:Class="DataGridSoHelpAttempt.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dataGridSoHelpAttempt="clr-namespace:DataGridSoHelpAttempt"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
Title="MainWindow" Height="350" Width="525" x:Name="This">
<Window.DataContext>
<dataGridSoHelpAttempt:MainViewModel/>
</Window.DataContext>
<Grid x:Name="MyGrid">
<DataGrid x:Name="MyDataGrid" ItemsSource="{Binding DataSource}" AutoGenerateColumns="False">
<i:Interaction.Behaviors>
<dataGridSoHelpAttempt:ColumnSelectingBehavior TotalPresenterVisibility="{Binding TotalsVisibility, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</i:Interaction.Behaviors>
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
<DataGridTextColumn Header="Comments" Binding="{Binding Comments}" Width="150"/>
<DataGridTextColumn Header="Price (click to see total)" Binding="{Binding Price, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Bottom">
<TextBlock Visibility="{Binding TotalsVisibility, UpdateSourceTrigger=PropertyChanged}">
<Run Text="Total price:"></Run>
<Run Text="{Binding TotalValue, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}"></Run>
</TextBlock>
</StackPanel>
</Grid></Window>
2. View models and models code:
public class MainViewModel:BaseObservableObject
{
private Visibility _visibility;
private ICommand _command;
private Visibility _totalsVisibility;
private double _totalValue;
public MainViewModel()
{
Visibility = Visibility.Collapsed;
TotalsVisibility = Visibility.Collapsed;
DataSource = new ObservableCollection<BaseData>(new List<BaseData>
{
new BaseData {Name = "Uncle Vania", Description = "A.Chekhov, play", Comments = "worth reading", Price = 25},
new BaseData {Name = "Anna Karenine", Description = "L.Tolstoy, roman", Comments = "worth reading", Price = 35},
new BaseData {Name = "The Master and Margarita", Description = "M.Bulgakov, novel", Comments = "worth reading", Price = 56},
});
}
public ICommand Command
{
get
{
return _command ?? (_command = new RelayCommand(VisibilityChangingCommand));
}
}
private void VisibilityChangingCommand()
{
Visibility = Visibility == Visibility.Collapsed ? Visibility.Visible : Visibility.Collapsed;
}
public ObservableCollection<BaseData> DataSource { get; set; }
public Visibility Visibility
{
get { return _visibility; }
set
{
_visibility = value;
OnPropertyChanged();
}
}
public ObservableCollection<BaseData> ColumnCollection
{
get { return DataSource; }
}
public Visibility TotalsVisibility
{
get { return _totalsVisibility; }
set
{
_totalsVisibility = value;
OnPropertyChanged();
}
}
public double TotalValue
{
get { return ColumnCollection.Sum(x => x.Price); }
}
}
public class BaseData:BaseObservableObject
{
private string _name;
private string _description;
private string _comments;
private int _price;
public virtual string Name
{
get { return _name; }
set
{
_name = value;
OnPropertyChanged();
}
}
public virtual object Description
{
get { return _description; }
set
{
_description = (string) value;
OnPropertyChanged();
}
}
public string Comments
{
get { return _comments; }
set
{
_comments = value;
OnPropertyChanged();
}
}
public int Price
{
get { return _price; }
set
{
_price = value;
OnPropertyChanged();
}
}
}
3. Behavior code:
public class ColumnSelectingBehavior : Behavior<DataGrid>
{
public static readonly DependencyProperty TotalPresenterVisibilityProperty = DependencyProperty.Register(
"TotalPresenterVisibility", typeof (Visibility), typeof (ColumnSelectingBehavior), new PropertyMetadata(Visibility.Collapsed));
public Visibility TotalPresenterVisibility
{
get { return (Visibility) GetValue(TotalPresenterVisibilityProperty); }
set { SetValue(TotalPresenterVisibilityProperty, value); }
}
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.Sorting += AssociatedObjectOnSorting;
}
private void AssociatedObjectOnSorting(object sender, DataGridSortingEventArgs dataGridSortingEventArgs)
{
var columnSortMemberPath = dataGridSortingEventArgs.Column.SortMemberPath;
if(columnSortMemberPath != "Price")
return;
TotalPresenterVisibility = TotalPresenterVisibility == Visibility.Visible
? Visibility.Collapsed
: Visibility.Visible;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.Sorting -= AssociatedObjectOnSorting;
}
}
4. BaseObservableObject code (for .net 4.5):
public class BaseObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual void OnPropertyChanged<T>(Expression<Func<T>> raiser)
{
var propName = ((MemberExpression)raiser.Body).Member.Name;
OnPropertyChanged(propName);
}
protected bool Set<T>(ref T field, T value, [CallerMemberName] string name = null)
{
if (!EqualityComparer<T>.Default.Equals(field, value))
{
field = value;
OnPropertyChanged(name);
return true;
}
return false;
}
}
I'll glad to help in case you will have problems wit the code. Regards.

Categories