Don't fire RelayCommand - wpf

I have a list in and relaycommand viewmodel,
private List<PurchaseInvoiceDetail> detailList = new List<PurchaseInvoiceDetail>();
public RelayCommand AddCommand { get; set; }
ICollectionView _detailCollection;
public ICollectionView DetailCollection
{
get { return _detailCollection; }
set
{
if (value != _detailCollection)
{
_detailCollection = value;
RaisePropertyChanged("DetailCollection");
}
}
}
when i use DetailCollection in constructor,dont fire relaycommand.
public PurchaseInvoiceDetailViewModel(PurchaseInvoice item)
{
if (item != null)
{
Number = item.Number;
CustomerId = item.CustomerId;
Date = new PersianDate((DateTime)item.Date);
_purchaseInvoice = item.Id;
detailList = _db.PurchaseInvoiceDetails.Where(m => m.PurchaseInvoiceId == item.Id).ToList();
CollectionViewSource.GetDefaultView(detailList).Refresh();
DetailCollection = CollectionViewSource.GetDefaultView(detailList);
}
AddCommand=new RelayCommand(() =>
{
var goods = _db.Goods.Find(GoodsId);
detailList.Add(new PurchaseInvoiceDetail(){GoodsId = GoodsId,Goods = goods,Count = Count,Price = Price,Id=0,PurchaseInvoiceId = 0});
CollectionViewSource.GetDefaultView(detailList).Refresh();
DetailCollection = CollectionViewSource.GetDefaultView(detailList);
});
}
but when i comment DetailCollection ,it work ok..
in view
<Button Margin="0 0 5 0 " Width="90" Command="{Binding AddCommand}"
Style="{StaticResource MaterialDesignRaisedButton}" >
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Kind="Plus" />
<TextBlock >َAdd</TextBlock>
</StackPanel>
</Button>
<DataGrid CanUserDeleteRows="True" CellStyle="{StaticResource MaterialDesignDataGridCell}" Name="ListView"
IsReadOnly="True" BorderBrush="{DynamicResource MaterialDesignDivider}" VerticalAlignment="Top" BorderThickness="1" Height="200" Margin="0" AutoGenerateColumns="False"
ItemsSource="{Binding Path=DetailCollection}"
>
<DataGrid CanUserDeleteRows="True" CellStyle="{StaticResource MaterialDesignDataGridCell}" Name="ListView"
IsReadOnly="True" BorderBrush="{DynamicResource MaterialDesignDivider}" VerticalAlignment="Top"
BorderThickness="1" Height="200" Margin="0" AutoGenerateColumns="False"
ItemsSource="{Binding Path=DetailCollection}"
>
<DataGrid.Columns>
<DataGridTextColumn Width="100"
Header="کد کالا" Binding="{Binding Path=Goods.Code}"/>
<DataGridTextColumn Header="نام کالا" Binding="{Binding Path=Goods.Name}" Width="200"/>
<DataGridTextColumn Binding="{Binding Path=Count}" Width="150"
dataGridFilterLibrary:DataGridColumnExtensions.IsCaseSensitiveSearch="True"
Header="تعداد"/>
<DataGridTextColumn Header="قیمت" Binding="{Binding Path=Price}" Width="*"/>
</DataGrid.Columns>
<DataGrid.InputBindings>
<KeyBinding
Key="Delete"
Command="{Binding DeleteCommand}" CommandParameter="{Binding SelectedIndex, ElementName=ListView}"/>
</DataGrid.InputBindings>
</DataGrid>

Related

datagride Mvvm update and insert from external fields

I have data grid that I want to update from external fields
I don't want to directly affect the data base
<DataGrid
AlternatingRowBackground="CadetBlue "
AutoGenerateColumns="False"
CanUserAddRows="False"
CanUserDeleteRows="False"
IsReadOnly="True"
ItemsSource="{Binding Path=Addresss ,Mode=TwoWay}"
SelectedItem="{Binding Path=Address, Mode=OneWayToSource}"
ColumnHeaderStyle="{StaticResource CenterColumnHeader}"
CellStyle="{StaticResource DataGridContentCellCentering}">
<DataGrid.Columns>
<DataGridTextColumn
Width="70"
Binding="{Binding Path=AddType}"
Header="النوع"
/>
<DataGridTextColumn
Width="80"
Binding="{Binding Path=AddAdjective}"
Header="الوصف" />
<DataGridTextColumn
Width="250"
Binding="{Binding Path=AddAddress}"
Header="العنوان" />
</DataGrid.Columns>
</DataGrid>
I made a combo box
<ComboBox x:Name="Cbox1" Width="69"
materialDesign:HintAssist.Hint="النوع"
Background="#252525"
ItemsSource="{Binding Path=AddTypelist}"
SelectedValue="{Binding Path=Addressl.AddType}"
Style="{StaticResource MaterialDesignFilledComboBoxFocus}"
IsTextSearchEnabled="True" IsTextSearchCaseSensitive="True"/>
I don't want the change to happen automatically. When I change it in the combo box, I want the process to be done with a button
I tried this method
public AddressTable Address
{
get => _address;
set
{
_address = value;
_addressl = _address;
NotifyOfPropertyChange(()=>Address);
}
}
private AddressTable _addressl;
public AddressTable Addressl
{
get => _addressl;
set
{
_addressl = value;
NotifyOfPropertyChange(() => Addressl);
}
}
But it didn't work

Caliburn.Micro: How to bind a function to a context menu item in the RowDetailsTemplate of a DataGrid?

I have a datagrid of Items that includes a datagrid of SubItems for the row details. There is a context menu for the main "Items" datagrid with functions to add or remove items, this is working fine. There is also a context menu for the row details datagrid "SubItems" with similar functions that I cannot get to bind properly. If executed i get the following exception "System.Exception: 'No target found for method AddSubItem.'"
I have desperately tried many other solutions that were suggested on other posts but nothing has worked so far. I appreciate any insight. Below is my test code.
ShellViewModel:
using System;
using Caliburn.Micro;
using ContextMenuTest.Models;
namespace ContextMenuTest.ViewModels
{
public class ShellViewModel : Screen
{
public static Random rnd = new Random();
private BindableCollection<ItemModel> items = new BindableCollection<ItemModel>();
public BindableCollection<ItemModel> Items
{
get { return items; }
set
{
items = value;
NotifyOfPropertyChange(() => Items);
}
}
private ItemModel selectedItem = new ItemModel(rnd);
public ItemModel SelectedItem
{
get { return selectedItem; }
set
{
selectedItem = value;
NotifyOfPropertyChange(() => SelectedItem);
}
}
private SubItemModel selectedSubItem = new SubItemModel(rnd);
public SubItemModel SelectedSubItem
{
get { return selectedSubItem; }
set
{
selectedSubItem = value;
NotifyOfPropertyChange(() => SelectedSubItem);
}
}
public ShellViewModel()
{
for(int i = 0; i < 10; i++)
{
Items.Add(new ItemModel(rnd));
}
}
public void AddItem()
{
Items.Add(new ItemModel(rnd));
}
public void RemoveItem()
{
Items.Remove(SelectedItem);
}
public void AddSubItem(object e)
{
var _item = e as ItemModel;
_item.SubItems.Add(new SubItemModel(rnd));
}
public void RemoveSubItem(object e)
{
var _item = e as ItemModel;
_item.SubItems.Remove(SelectedSubItem);
}
}
}
ShellView:
<Window x:Class="ContextMenuTest.Views.ShellView"
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:ContextMenuTest.Views"
xmlns:cal="http://www.caliburnproject.org"
mc:Ignorable="d"
Title="ShellView" Height="450" Width="800"
>
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<DataGrid x:Name="Items" Grid.Row="0" AutoGenerateColumns="False" CanUserResizeColumns="True" CanUserAddRows="false"
VerticalAlignment="Stretch" VerticalScrollBarVisibility="Auto" MinHeight="100" SelectedItem="{Binding SelectedItem}">
<DataGrid.ContextMenu>
<ContextMenu cal:Action.TargetWithoutContext="{Binding Path=PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Add Item" cal:Message.Attach="AddItem()"/>
<MenuItem Header="Remove Item" cal:Message.Attach="RemoveItem()"/>
</ContextMenu>
</DataGrid.ContextMenu>
<DataGrid.Columns >
<DataGridTextColumn Header="ID" Binding="{Binding Path=ID, UpdateSourceTrigger=PropertyChanged}" Width="*" IsReadOnly="True"/>
<DataGridTextColumn Header="Name" Binding="{Binding Path=Name, UpdateSourceTrigger=PropertyChanged}" Width="*"/>
</DataGrid.Columns>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<DataGrid ItemsSource="{Binding Path=SubItems}" AutoGenerateColumns="False" CanUserResizeColumns="True" CanUserAddRows="false"
VerticalAlignment="Stretch" VerticalScrollBarVisibility="Auto" MinHeight="100"
SelectedItem="{Binding Path=SelectedSubItem, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Grid}}">
<DataGrid.ContextMenu>
<ContextMenu cal:Action.TargetWithoutContext="{Binding Path=PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Add Sub Item" cal:Message.Attach="AddSubItem($dataContext)"/>
<MenuItem Header="Remove Sub Item" cal:Message.Attach="RemoveSubItem($dataContext)"/>
</ContextMenu>
</DataGrid.ContextMenu>
<DataGrid.Columns>
<DataGridTextColumn Header="ID" Binding="{Binding Path=ID}" Width="auto" IsReadOnly="True"/>
<DataGridTextColumn Header="Name" Binding="{Binding Path=Name, UpdateSourceTrigger=PropertyChanged}" Width="auto"/>
<DataGridTextColumn Header="Value" Binding="{Binding Path=Value, UpdateSourceTrigger=PropertyChanged}" Width="auto"/>
</DataGrid.Columns>
</DataGrid>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
</Grid>
</Window>
ItemModel:
using Caliburn.Micro;
using System;
namespace ContextMenuTest.Models
{
public class ItemModel
{
public Guid ID { get; set; }
public string Name { get; set; }
public BindableCollection<SubItemModel> SubItems { get; set; } = new BindableCollection<SubItemModel>();
public ItemModel(Random rnd)
{
ID = Guid.NewGuid();
Name = "Item " + ID.ToString().Substring(3, 5);
for (int i = 0; i < 5; i++)
{
SubItems.Add(new SubItemModel(rnd));
}
}
}
}
SubItemModel:
using System;
namespace ContextMenuTest.Models
{
public class SubItemModel
{
public Guid ID { get; set; }
public string Name { get; set; }
public int Value { get; set; }
public SubItemModel(Random rnd)
{
ID = Guid.NewGuid();
Name = "SubItem " + ID.ToString().Substring(3,5);
Value = rnd.Next();
}
}
}
Try using TagHelper. It works for your requirement.sample code is as below.
<Grid Background="White" HorizontalAlignment="Stretch" Height="200" Name="GridLayout">
<ListBox x:Name="ListBoxItems">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Tag="{Binding DataContext, ElementName=GridLayout}">
<Grid.ContextMenu>
<ContextMenu Name="cm" cal:Action.TargetWithoutContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
<MenuItem Header="Open"
cal:Message.Attach="Open($dataContext)">
</MenuItem>
</ContextMenu>
</Grid.ContextMenu>
<TextBlock VerticalAlignment="Center">
.. text..
</TextBlock>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>

change data grid based on combobox selection WPF

I am trying to populate a datagrid based on the selection from a combobox, I am new to wpf so I am not sure if my issue is the the databinding or what. Here is my VM:
namespace WasteTracker
{
public class MenuItemViewModel : INotifyPropertyChanged
{
DataSource data = new DataSource();
private ObservableCollection<StationList> stationlistcb = new
ObservableCollection<StationList>();
private ObservableCollection<MenuItem> menuitemdg = new
ObservableCollection<MenuItem>();
//methods to populate combobox of stations and datagrid of menu items
for that station
#region Load Stations and Menu Methods
public void LoadStationList()
{
stationlistcb = new ObservableCollection<StationList>
(data.Stations());
}
public void LoadMenuItems(int stationid)
{
menuitemdg = new ObservableCollection<MenuItem>
(from onemenuitem in data.MenuItems()
where onemenuitem.StationId.Equals(stationid)
select onemenuitem);
OnPropertyChanged("MenuItemData");
}
#endregion
public ObservableCollection<StationList> StationList
{
get
{
return stationlistcb;
}
}
public ObservableCollection<MenuItem> MenuItemList
{
get
{
return menuitemdg;
}
}
/// <summary>
/// Called when [property changed].
/// </summary>
/// <param name="PropertyName">Name of the property.</param>
protected void OnPropertyChanged(string PropertyName)
{
VerifyPropertyName(PropertyName);
if (PropertyChanged != null)
{
PropertyChanged(this, new
PropertyChangedEventArgs(PropertyName));
}
}
#region Propertychange Methods
/// <summary>
/// Warns the developer if this object does not have
/// a public property with the specified name. This
/// method does not exist in a Release build.
/// </summary>
[Conditional("DEBUG")]
[DebuggerStepThrough]
private void VerifyPropertyName(string propertyName)
{
// Verify that the property name matches a real,
// public, instance property on this object.
if (TypeDescriptor.GetProperties(this)[propertyName] == null)
{
string msg = "Invalid property name: " + propertyName;
throw new Exception(msg);
}
}
#endregion
public event PropertyChangedEventHandler PropertyChanged;
}
}
And here is the XAML for the page:
<TextBlock Grid.Row="0" Grid.ColumnSpan="3" FontSize="35"
HorizontalAlignment="Center" VerticalAlignment="Top" Text="Microsoft
SVMT Waste Tracker" Height="50" Width="480" Margin="44,0" />
<TextBlock Grid.Row="1" Grid.ColumnSpan="3" FontSize="30"
HorizontalAlignment="Center" VerticalAlignment="Top" Text="Waste
Entry" Height="50" Width="166" Margin="10,0,44,0" />
<TextBlock Grid.Row="2" Grid.Column="0" Text="Station" FontSize="30"
HorizontalAlignment="Center" VerticalAlignment="top" />
<TextBlock Grid.Row="2" Grid.Column="3" Text="Date" FontSize="30"
HorizontalAlignment="Center" VerticalAlignment="top" />
<DatePicker Grid.Row="3" Grid.Column="2" Grid.RowSpan="2" FontSize="30"
HorizontalAlignment="Center" VerticalAlignment="Center"
Width="290" Height="42" Margin="0,19,10,22" />
<ComboBox Name="StationBox" Grid.Row="3" Grid.Column="0"
Grid.RowSpan="2" FontSize="30" ItemsSource="{Binding StationList}"
DisplayMemberPath="StationName" HorizontalAlignment="Center"
VerticalAlignment="Center" Width="300" Height="42"
Margin="0,19,0,23"
SelectionChanged="Station_SelectionChanged" />
<DataGrid ItemsSource="{Binding MenuItemList}"
DisplayMemberPath="MenuItemText" AutoGenerateColumns="False"
Grid.Row="5" Grid.ColumnSpan="3" CanUserAddRows="True"
AlternatingRowBackground="AliceBlue"
IsSynchronizedWithCurrentItem="True" >
<DataGrid.Columns>
<DataGridTextColumn Header="Menu Item" Binding="{Binding
MenuItemText}" HeaderStyle="{StaticResource CenterGridHeader}"
CellStyle="{StaticResource CenterCellText}"
IsReadOnly="True" CanUserResize="False"
FontSize="36" Width="*"/>
<DataGridTextColumn Header="UoM" Binding="{Binding UoM}"
HeaderStyle="{StaticResource CenterGridHeader}" CellStyle="
{StaticResource CenterCellText}"
IsReadOnly="True" FontSize="36"
CanUserResize="False" Width="*" />
<DataGridTextColumn Header="Left Over" Binding="{Binding
UserInput}" HeaderStyle="{StaticResource CenterGridHeader}"
CellStyle="{StaticResource CenterCellText}"
FontSize="36" IsReadOnly="False"
CanUserResize="False" Width="*"/>
<DataGridTextColumn Header="UoM" Binding="{Binding UoM}"
HeaderStyle="{StaticResource CenterGridHeader}" CellStyle="
{StaticResource CenterCellText}"
IsReadOnly="True" FontSize="36"
CanUserResize="False" Width="*" />
<DataGridTextColumn Header="Par" Binding="{Binding Par}"
HeaderStyle="{StaticResource CenterGridHeader}" CellStyle="
{StaticResource CenterCellText}"
IsReadOnly="True" FontSize="36"
CanUserResize="False" Width="*"/>
<DataGridTextColumn Header="UoM" Binding="{Binding UoM}"
HeaderStyle="{StaticResource CenterGridHeader}" CellStyle="
{StaticResource CenterCellText}"
IsReadOnly="True" FontSize="36"
CanUserResize="False" Width="*" />
</DataGrid.Columns>
</DataGrid>
</Grid>
this is the xaml.cs:
public MenuItemViewModel _objViewModel = new MenuItemViewModel();
public EnterWaste()
{
InitializeComponent();
SourceContext();
InitialOperations();
}
private void Station_SelectionChanged(object sender,
SelectionChangedEventArgs e)
{
_objViewModel.LoadMenuItems((StationBox.SelectedItem as
MenuItem).StationId);
}
With this code currently the combobox is currently populated with the correct info, however when I make a selection from the combobox the datagrid will not display the correct info. Being new to wpf I have done a lot googling however the closest thing I can find in cascading comboboxes, and that solution really didn't help. Any suggestions would be appreciated.

what to use besides OnCurrentChanged since it is not firing WPF MVVM

I have a combobox with 2 date pickers on my main xaml file
<ComboBox Margin="5" Height="23" HorizontalAlignment="Left" VerticalAlignment="Top" Width="90"
x:Name="datOpt"
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding Path=dateOptObj.dates}"
Background="{x:Null}" />
<DatePicker Padding="5,5,5,5"
Text="{Binding Path=dateOptObj.openDate, Mode=TwoWay}"/>
<TextBlock Padding="5,5,5,5" Text=" to "/>
<DatePicker Padding="5,5,5,5"
Text="{Binding Path=dateOptObj.closeDate, Mode=TwoWay}" />
in the viewmodel I create an instance like this
public mdDateOptions dateOptObj { get; set; }
public vwMain()
{
try
{
// Initialize the panel switches
dateOptObj = new mdDateOptions();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
the class of mdDateOptions is as follows
class mdDateOptions : vwBase
{
private DateTime _openDate;
public DateTime openDate
{
get
{
return _openDate;
}
set
{
if (_openDate != value)
{
_openDate = value;
RaisePropertyChanged("openDate");
}
}
}
private DateTime _closeDate;
public DateTime closeDate
{
get
{
return _closeDate;
}
set
{
if (_closeDate != value)
{
_closeDate = value;
RaisePropertyChanged("closeDate");
}
}
}
private DateTime _openDatePrevious;
public DateTime openDatePrevious
{
get
{
return _openDatePrevious;
}
set
{
if (_openDatePrevious != value)
{
_openDatePrevious = value;
RaisePropertyChanged("openDatePrevious");
}
}
}
private DateTime _closeDatePrevious;
public DateTime closeDatePrevious
{
get
{
return _closeDatePrevious;
}
set
{
if (_closeDatePrevious != value)
{
_closeDatePrevious = value;
RaisePropertyChanged("closeDatePrevious");
}
}
}
private ICollectionView _datOpts;
public ObservableCollection<string> dates { get; private set; }
public ICollectionView datesView
{
get
{
return _datOpts;
}
}
public mdDateOptions()
{
dates = new ObservableCollection<string>();
dates.Add("Rolling Year");
dates.Add("Year to Date");
dates.Add("Last Year");
_datOpts = CollectionViewSource.GetDefaultView(dates);
_datOpts.CurrentChanged += new EventHandler(OnCurrentChanged);
}
public mdDateOptions(Boolean value)
{
dates = new ObservableCollection<string>();
dates.Add("Rolling Year");
dates.Add("Year to Date");
dates.Add("Last Year");
_datOpts = CollectionViewSource.GetDefaultView(dates);
_datOpts.CollectionChanged += this.OnCurrentChanged;
}
public void OnCurrentChanged(object sender, EventArgs e)
{
string currSel = (string)_datOpts.CurrentItem;
DateTime p_date = new DateTime();
p_date = DateTime.Today;
switch (currSel)
{
case "Rolling Year":
openDate = DateTime.Today.AddYears(-1);
closeDate = DateTime.Today;
openDatePrevious = DateTime.Today.AddYears(-2);
closeDatePrevious = DateTime.Today.AddYears(-1);
break;
case "Year to Date":
openDate = new DateTime(DateTime.Today.Year, 1, 1);
closeDate = DateTime.Today;
openDatePrevious = new DateTime(DateTime.Today.AddYears(-1).Year, 1, 1);
closeDatePrevious = DateTime.Today.AddYears(-1);
break;
case "Last Year":
openDate = new DateTime(DateTime.Today.AddYears(-1).Year, 1, 1);
closeDate = new DateTime(DateTime.Today.AddYears(-1).Year, 12, 31);
openDatePrevious = new DateTime(DateTime.Today.AddYears(-2).Year, 1, 1);
closeDatePrevious = new DateTime(DateTime.Today.AddYears(-2).Year, 12, 31);
break;
default:
MessageBox.Show("Unknown Date Option");
break;
}
}
}
When the program first loads it goes into the OncurrentChanged and loads the appropriate dates. But after when i am clicking a button in a userControl on the same main xaml file the dateOptObj is null and when I try to create a new instance of the mdDateOptions it doesnt trigger the onCurrentChanged because nothing has changed! My question how can I get my dateOptObj to contain the proper dates when clicking my button in the userControl on the main xaml file. Thanks in advance!
This is the main Xaml file
<Window x:Class="ManagementDashboard.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:ManagementDashboard"
Title="Dashboard Home" Height="768" Width="1024">
<Window.Resources>
<vm:vwMain x:Key="viewModel" />
</Window.Resources>
<DockPanel x:Name="viewModel"
DataContext="{Binding Source={StaticResource viewModel}}" >
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<TextBlock Padding="5,5,5,5" Text="Date Options: "/>
<ComboBox Margin="5" Height="23" HorizontalAlignment="Left" VerticalAlignment="Top" Width="90"
x:Name="datOpt"
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding Path=dateOptObj.dates}"
Background="{x:Null}" />
<DatePicker Padding="5,5,5,5"
SelectedDate="{Binding Path=dateOptObj.openDate, Mode=TwoWay}"/>
<TextBlock Padding="5,5,5,5" Text=" to "/>
<DatePicker Padding="5,5,5,5"
SelectedDate="{Binding Path=dateOptObj.closeDate, Mode=TwoWay}" />
<TextBlock Padding="5,5,5,5" Text="Rep Filter: "/>
<ComboBox Margin="5" Height="23" HorizontalAlignment="Left" VerticalAlignment="Top" Width="200"
x:Name="repOption"
IsSynchronizedWithCurrentItem="True"
DataContext="{Binding Source={StaticResource viewModel}}"
ItemsSource="{Binding Path=reps}"
DisplayMemberPath="AEname" />
<!--Background="{x:Null}" />-->
<Button Margin="5" Width="100" Height="20" Content="Reset Dates" Command="{Binding Path=Refill}" />
</StackPanel>
<StackPanel Orientation="Horizontal" DockPanel.Dock="Bottom">
<Button Margin="5" Width="100" Height="20" Content="Exit" Command="{Binding Path=ExitCommand}" />
</StackPanel>
<vm:StatPanel DockPanel.Dock="Right" Loaded="StatPanel_Loaded" />
<vm:MainBody DataContext="{Binding Source={StaticResource viewModel}}"/>
</DockPanel>
this is the code behind
public partial class MainWindow : Window
{
vwMain _viewModel;
public MainWindow()
{
InitializeComponent();
// Initialize the view Model
_viewModel = (vwMain)this.FindResource("viewModel");
}
private void StatPanel_Loaded(object sender, RoutedEventArgs e)
{
}
}
this is the part of the XAML of the UserControl
<Expander Header="New Account Stats" IsExpanded="{Binding Path=newAcctPanel, Mode=TwoWay}" ExpandDirection="Down">
<DataGrid
x:Name="m_DataGrid"
ItemsSource="{Binding}"
DataContext="{Binding Path=dashNewAcct.newAcctStats}"
VerticalAlignment="Stretch" AutoGenerateColumns="False"
ColumnWidth="Auto">
<DataGrid.Columns>
<!--<DataGridTextColumn Header="Sector"
Binding="{Binding Path=sector}" />
<DataGridTextColumn Header="Security"
Binding="{Binding Path=totalSecurities}" />
<DataGridTextColumn Header="CD"
Binding="{Binding Path=totalCD}" />
<DataGridTextColumn Header="LPC"
Binding="{Binding Path=totalLPC}" />
<DataGridTextColumn Header="BSMS"
Binding="{Binding Path=totalBSMS, StringFormat='{}{0}'}" />
<DataGridTextColumn Header="Totals"
Binding="{Binding Path=total, StringFormat='{}{0}'}" />-->
<DataGridTemplateColumn>
<DataGridTemplateColumn.Header>Sector</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Content="{Binding Path=sector}"></Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="Security">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Name="Security" Content="{Binding Path=totalSecurities}" Command="{Binding Source={StaticResource viewModel}, Path=filterGridCommand}">
<Button.CommandParameter>
<MultiBinding Converter="{StaticResource PassThroughConverter}">
<Binding Path="sector"/>
<Binding ElementName="Security" Path="Name"/>
</MultiBinding>
</Button.CommandParameter>
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.Header>CD</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Name="CD" Content="{Binding Path=totalCD}" Command="{Binding Source={StaticResource viewModel}, Path=filterGridCommand}">
<Button.CommandParameter>
<MultiBinding Converter="{StaticResource PassThroughConverter}">
<Binding Path="sector"/>
<Binding ElementName="CD" Path="Name"/>
</MultiBinding>
</Button.CommandParameter>
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.Header>LPC</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Name="LPC" Content="{Binding Path=totalLPC}" Command="{Binding Source={StaticResource viewModel}, Path=filterGridCommand}">
<Button.CommandParameter>
<MultiBinding Converter="{StaticResource PassThroughConverter}">
<Binding Path="sector"/>
<Binding ElementName="LPC" Path="Name" />
</MultiBinding>
</Button.CommandParameter>
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.Header>BSMS</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Name="BSMS" Content="{Binding Path=totalBSMS}" Command="{Binding Source={StaticResource viewModel}, Path=filterGridCommand}">
<Button.CommandParameter>
<MultiBinding Converter="{StaticResource PassThroughConverter}">
<Binding Path="sector"/>
<Binding ElementName="BSMS" Path="Name" />
</MultiBinding>
</Button.CommandParameter>
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.Header>Totals</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Content="{Binding Path=total}"></Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Expander>
OnCurrentChanged fires properly, your Bindings are wrong. Bind the DateTime properties to SelectedDate not Text.
<DatePicker Padding="5,5,5,5"
SelectedDate="{Binding Path=dateOptObj.openDate, Mode=TwoWay}" />
<DatePicker Padding="5,5,5,5"
SelectedDate="{Binding Path=dateOptObj.closeDate, Mode=TwoWay}" />

Binding not triggering Action<>

I have some code like this
this is a custom datagrid which displays hierarchical data which should close and open.
<UserControl.DataContext>
<loc:Def1 x:Name="initdef1"/>
</UserControl.DataContext>
<Grid x:Name="LayoutRoot" HorizontalAlignment="Center" VerticalAlignment="Center" >
<data:DataGrid x:Name="_dataGrid" AutoGenerateColumns="False"
ItemsSource="{Binding Display, Mode=OneWay}"
SelectionMode="Extended" >
<data:DataGrid.Columns>
<data:DataGridTemplateColumn Header="Col1">
<data:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" >
<CheckBox IsChecked="{Binding IsExpanded, Mode=TwoWay}" Margin="{Binding Path=Level, Converter={StaticResource ConvertToThickness}}"/>
<TextBlock Text="{Binding Cells[0]}" Margin="4" />
</StackPanel>
</DataTemplate>
</data:DataGridTemplateColumn.CellTemplate>
</data:DataGridTemplateColumn>
<data:DataGridTextColumn Header="Col2" Binding="{Binding Cells[1]}" />
</data:DataGrid.Columns>
</data:DataGrid>
with this is def1
this class has the actual logic for all the processing and loading and mapping the data to the grid.
public Def1()
{
_columns = new List<ColumnDef>();
_source = new ObservableCollection<Def2>();
Def2.RowExpanding += new Action<Def2>(RowDef_RowExpanding);
Def2.RowCollapsing += new Action<Def2>(RowDef_RowCollapsing);
}
void RowDef_RowExpanding(Def2 row)
{
foreach (RowDef child in row.Children)
child.IsVisible = true;
OnPropertyChanged("Display");
}
void RowDef_RowCollapsing(Def2 row)
{
foreach (Def2 child in row.Children)
{
if (row.IsExpanded.HasValue && row.IsExpanded.Value)
RowDef_RowCollapsing(child);
child.IsVisible = false;
}
OnPropertyChanged("Display");
}
and this in def2
this class has the logic on how should the rows behave.
public bool? IsExpanded
{
get { return _isExpanded; }
set
{
if (_isExpanded != value)
{
_isExpanded = value;
if (_isExpanded.Value)
{
if (RowDef.RowExpanding != null)
RowDef.RowExpanding(this);
}
else
{
if (RowDef.RowCollapsing != null)
RowDef.RowCollapsing(this);
}
}
}
}
The thing is when the checkbox is checked or unchecked nothing happens.
Ok I found the answer from a similar post wpf 4.0 datagrid template column two-way binding problem
So I changed the code to
<CheckBox IsChecked="{Binding Mode=TwoWay, Path=IsExpanded, UpdateSourceTrigger=PropertyChanged}" Margin="{Binding Path=Level, Converter={StaticResource ConvertToThickness}}" Checked="CheckBox_Checked" Unchecked="CheckBox_Unchecked" x:Name="checkbox1"/>
Now it works.
But can anybody explain why i needed to set UpdateSourceTrigger=PropertyChanged ?
It's not always required.
Thanks

Resources