1

I have a working code with a Datagrid as the main control. I used a Datagrid as it is very easy to bind data into it.

My code requires moving cells into other columns so I always need to check which cell I am on when the mouse is clicked, as well as when it is released.

My current implementation is working as expected. However, the way I check for the row and cell is through the VIEW's code-behind. My project leader is looking for an alternative to have this done thru binding as he wants to keep the VIEW's code-behind as clean as possible. I have tried all I could but I can't find properties which would give me both the cells column and row index.

Please see the code below. (Omitted some of the columns as it would exceed the limit.)

the XAML:

<UserControl x:Class="Widget5.View.WorkItemsDisplay"
             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:converter="clr-namespace:Widget5.Converter"             
             mc:Ignorable="d" 
             d:DesignHeight="630" Width="690" Padding="0" Margin="0">

    <UserControl.Resources>
        <converter:RowNumberConverter x:Key="rowNumberConverter" />
        <converter:HourSlotToBrushConverter x:Key="hourSlotColorConverter" />

    </UserControl.Resources>

    <Grid Margin="0" Width="690" HorizontalAlignment="Left" MouseRightButtonUp="Grid_MouseRightButtonUp" MouseUp="Grid_MouseUp">
        <Grid.RowDefinitions>
            <RowDefinition Height="24"></RowDefinition>
            <RowDefinition></RowDefinition>
            <!--<RowDefinition Height="30"></RowDefinition>-->
        </Grid.RowDefinitions>

        <!--<Grid HorizontalAlignment="Left" Height="24" VerticalAlignment="Bottom" Grid.Row="2"
              Width="680">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="5" />
                <ColumnDefinition Width="50" />
                <ColumnDefinition Width="2" />
                <ColumnDefinition Width="50" />
                <ColumnDefinition Width="2" />
                <ColumnDefinition Width="50" />
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="50" />
                <ColumnDefinition Width="10" />
            </Grid.ColumnDefinitions>
            <Button Grid.Column="1" Width="48"
                    Command="{Binding AddCommand}">Add</Button>
            <Button Grid.Column="3" Width="48"
                    Command="{Binding DeleteCommand}">Delete</Button>
            <Button Grid.Column="5" Width="48"
                    Command="{Binding SaveCommand}">Save</Button>
            <Button Grid.Column="7" Width="48"
                    Command="{Binding RefreshCommand}">Refresh</Button>
        </Grid>-->

        <Grid HorizontalAlignment="Left" Height="24" VerticalAlignment="Top" Width="690" Grid.Row="0"
              Background="LightGray">

            <Grid.Resources>
                <Style TargetType="{x:Type TextBlock}">
                    <Setter Property="FontSize" Value="10"/>
                </Style>
            </Grid.Resources>

            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="22"/>
                <ColumnDefinition Width="20"/>
                <ColumnDefinition Width="123"/>
                <ColumnDefinition Width="30"/>
                <ColumnDefinition Width="20"/>
                <ColumnDefinition Width="20"/>
                <ColumnDefinition Width="20"/>
                <ColumnDefinition Width="20"/>
                <ColumnDefinition Width="20"/>
                <ColumnDefinition Width="20"/>
                <ColumnDefinition Width="20"/>
                <ColumnDefinition Width="20"/>
                <ColumnDefinition Width="20"/>
                <ColumnDefinition Width="20"/>
                <ColumnDefinition Width="20"/>
                <ColumnDefinition Width="20"/>
                <ColumnDefinition Width="20"/>
                <ColumnDefinition Width="20"/>
                <ColumnDefinition Width="20"/>
                <ColumnDefinition Width="20"/>
                <ColumnDefinition Width="20"/>
                <ColumnDefinition Width="20"/>
                <ColumnDefinition Width="20"/>
                <ColumnDefinition Width="20"/>
                <ColumnDefinition Width="20"/>
                <ColumnDefinition Width="20"/>
                <ColumnDefinition Width="20"/>
                <ColumnDefinition Width="20"/>
            </Grid.ColumnDefinitions>
            <Border Grid.Column="0" BorderThickness="1,1,0,1" BorderBrush="Black"/>
            <Border Grid.Column="1" BorderThickness="1,1,0,1" BorderBrush="Black"/>
            <Border Grid.Column="2" BorderThickness="1,1,0,1" BorderBrush="Black"/>
            <Border Grid.Column="3" BorderThickness="1,1,0,1" BorderBrush="Black"/>
            <Border Grid.Column="4" BorderThickness="1,1,0,1" BorderBrush="Black"/>
            <Border Grid.Column="5" BorderThickness="1,1,0,1" BorderBrush="Black"/>
            <Border Grid.Column="6" BorderThickness="1,1,0,1" BorderBrush="Black"/>
            <Border Grid.Column="7" BorderThickness="1,1,0,1" BorderBrush="Black"/>
            <Border Grid.Column="8" BorderThickness="1,1,0,1" BorderBrush="Black"/>
            <Border Grid.Column="9" BorderThickness="1,1,0,1" BorderBrush="Black"/>
            <Border Grid.Column="10" BorderThickness="1,1,0,1" BorderBrush="Black"/>
            <Border Grid.Column="11" BorderThickness="1,1,0,1" BorderBrush="Black"/>
            <Border Grid.Column="12" BorderThickness="1,1,0,1" BorderBrush="Black"/>
            <Border Grid.Column="13" BorderThickness="1,1,0,1" BorderBrush="Black"/>
            <Border Grid.Column="14" BorderThickness="1,1,0,1" BorderBrush="Black"/>
            <Border Grid.Column="15" BorderThickness="1,1,0,1" BorderBrush="Black"/>
            <Border Grid.Column="16" BorderThickness="1,1,0,1" BorderBrush="Black"/>
            <Border Grid.Column="17" BorderThickness="1,1,0,1" BorderBrush="Black"/>
            <Border Grid.Column="18" BorderThickness="1,1,0,1" BorderBrush="Black"/>
            <Border Grid.Column="19" BorderThickness="1,1,0,1" BorderBrush="Black"/>
            <Border Grid.Column="20" BorderThickness="1,1,0,1" BorderBrush="Black"/>
            <Border Grid.Column="21" BorderThickness="1,1,0,1" BorderBrush="Black"/>
            <Border Grid.Column="22" BorderThickness="1,1,0,1" BorderBrush="Black"/>
            <Border Grid.Column="23" BorderThickness="1,1,0,1" BorderBrush="Black"/>
            <Border Grid.Column="24" BorderThickness="1,1,0,1" BorderBrush="Black"/>
            <Border Grid.Column="25" BorderThickness="1,1,0,1" BorderBrush="Black"/>
            <Border Grid.Column="26" BorderThickness="1,1,0,1" BorderBrush="Black"/>
            <Border Grid.Column="27" BorderThickness="1,1,1,1" BorderBrush="Black"/>

            <TextBlock Text="NO" HorizontalAlignment="Center" VerticalAlignment="Center"  Margin="0" FontSize="12"/>
            <TextBlock Text="削" HorizontalAlignment="Center" Grid.Column="1" VerticalAlignment="Center" Margin="0" FontSize="12"/>
            <TextBlock Text="中項目名称" Grid.Row="0" Grid.Column="2" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0" FontSize="12"/>
            <TextBlock Text="回数" HorizontalAlignment="Center" Grid.Column="3" VerticalAlignment="Center" Margin="0" FontSize="12"/>
            <TextBlock Text="5" Grid.Row="0" Grid.Column="4" HorizontalAlignment="Center" VerticalAlignment="Center"  Margin="0"/>
            <TextBlock Text="6" Grid.Row="0" Grid.Column="5" HorizontalAlignment="Center" VerticalAlignment="Center"  Margin="0"/>
            <TextBlock Text="7" Grid.Row="0" Grid.Column="6" HorizontalAlignment="Center" VerticalAlignment="Center"  Margin="0"/>
            <TextBlock Text="8" Grid.Row="0" Grid.Column="7" HorizontalAlignment="Center" VerticalAlignment="Center"  Margin="0"/>
            <TextBlock Text="9" Grid.Row="0" Grid.Column="8" HorizontalAlignment="Center" VerticalAlignment="Center"  Margin="0"/>
            <TextBlock Text="10" Grid.Row="0" Grid.Column="9"  HorizontalAlignment="Center" VerticalAlignment="Center"  Margin="0"/>
            <TextBlock Text="11" Grid.Row="0" Grid.Column="10" HorizontalAlignment="Center" VerticalAlignment="Center"  Margin="0"/>
            <TextBlock Text="12" Grid.Row="0" Grid.Column="11" HorizontalAlignment="Center" VerticalAlignment="Center"  Margin="0"/>
            <TextBlock Text="13" Grid.Row="0" Grid.Column="12" HorizontalAlignment="Center" VerticalAlignment="Center"  Margin="0"/>
            <TextBlock Text="14" Grid.Row="0" Grid.Column="13" HorizontalAlignment="Center" VerticalAlignment="Center"  Margin="0"/>
            <TextBlock Text="15" Grid.Row="0" Grid.Column="14" HorizontalAlignment="Center" VerticalAlignment="Center"  Margin="0"/>
            <TextBlock Text="16" Grid.Row="0" Grid.Column="15" HorizontalAlignment="Center" VerticalAlignment="Center"  Margin="0"/>
            <TextBlock Text="17" Grid.Row="0" Grid.Column="16"  HorizontalAlignment="Center" VerticalAlignment="Center"  Margin="0"/>
            <TextBlock Text="18" Grid.Row="0" Grid.Column="17" HorizontalAlignment="Center" VerticalAlignment="Center"  Margin="0"/>
            <TextBlock Text="19" Grid.Row="0" Grid.Column="18" HorizontalAlignment="Center" VerticalAlignment="Center"  Margin="0"/>
            <TextBlock Text="20" Grid.Row="0" Grid.Column="19" HorizontalAlignment="Center" VerticalAlignment="Center"  Margin="0"/>
            <TextBlock Text="21" Grid.Row="0" Grid.Column="20" HorizontalAlignment="Center" VerticalAlignment="Center"  Margin="0"/>
            <TextBlock Text="20" Grid.Row="0" Grid.Column="21" HorizontalAlignment="Center" VerticalAlignment="Center"  Margin="0"/>
            <TextBlock Text="23" Grid.Row="0" Grid.Column="22"  HorizontalAlignment="Center" VerticalAlignment="Center"  Margin="0"/>
            <TextBlock Text="0" Grid.Row="0" Grid.Column="23" HorizontalAlignment="Center" VerticalAlignment="Center"  Margin="0"/>
            <TextBlock Text="1" Grid.Row="0" Grid.Column="24" HorizontalAlignment="Center" VerticalAlignment="Center"  Margin="0"/>
            <TextBlock Text="2" Grid.Row="0" Grid.Column="25" HorizontalAlignment="Center" VerticalAlignment="Center"  Margin="0"/>
            <TextBlock Text="3" Grid.Row="0" Grid.Column="26" HorizontalAlignment="Center" VerticalAlignment="Center"  Margin="0"/>
            <TextBlock Text="4" Grid.Row="0" Grid.Column="27" HorizontalAlignment="Center" VerticalAlignment="Center"  Margin="0"/>
        </Grid>

        <DataGrid Name="ScheduleDG" ItemsSource="{Binding ScheduleTable, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                      Grid.Row="1" AutoGenerateColumns="False"  HeadersVisibility="None"
                      IsReadOnly="False" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Hidden" 
                      SelectionUnit="CellOrRowHeader" SelectionMode="Extended" Padding="0" FontSize="10" BorderThickness="1" BorderBrush="Black" HorizontalAlignment="Left" Width="690"
                      Margin="0,-1,-2,0" Height="Auto" AllowDrop="True" RowHeight="18" 
                      PreviewMouseLeftButtonUp="ScheduleTable_PreviewMouseLeftButtonUp" 
                      PreviewMouseLeftButtonDown="ScheduleTable_PreviewMouseLeftButtonDown" MouseMove="ScheduleDG_MouseMove">
            <!--<i:Interaction.Triggers>
                <i:EventTrigger EventName="MouseLeftButtonUp">
                    <i:InvokeCommandAction Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}},
                                    Path=DataContext.CellSelectedCommand}"
                                    CommandParameter="{Binding SelectedCells, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}}" />
                </i:EventTrigger>
                <i:EventTrigger EventName="MouseLeftButtonDown">
                    <i:InvokeCommandAction Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}},
                                    Path=DataContext.StartCellCommand}"
                                    CommandParameter="{Binding CurrentCell, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}}" />
                </i:EventTrigger>
                <i:EventTrigger EventName="MouseRightClick">
                    <i:InvokeCommandAction Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}},
                                    Path=DataContext.RightClickCommand}"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>-->

            <DataGrid.Columns>
                <DataGridTextColumn Header="NO" Width="22" IsReadOnly="True">
                    <DataGridTextColumn.HeaderStyle>
                        <Style TargetType="{x:Type DataGridColumnHeader}">
                            <Setter Property="FontSize" Value="10" />
                            <Setter Property="Margin" Value="0"/>
                        </Style>
                    </DataGridTextColumn.HeaderStyle>
                    <DataGridTextColumn.Binding>
                        <MultiBinding Converter="{StaticResource rowNumberConverter}">
                            <Binding />
                            <Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}" />
                        </MultiBinding>
                    </DataGridTextColumn.Binding>
                </DataGridTextColumn>
                <DataGridTemplateColumn Header="削">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <CheckBox x:Name="TestCheckBox" VerticalAlignment="Center" HorizontalAlignment="Center"
                                      IsChecked="{Binding isSelected, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTextColumn Header="中項目名称" Binding="{Binding TaskName}" Width="123"/>
                <DataGridTextColumn Header="回数"  Width="30"/>

                <!--<DataGridTemplateColumn Header="5" MaxWidth="10">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Background="{Binding _5, Converter={StaticResource  ResourceKey=hourSlotColorConverter}, UpdateSourceTrigger=PropertyChanged}"
                                     IsEnabled="False">
                                <i:Interaction.Triggers>
                                    <i:EventTrigger EventName="PreviewMouseDown">
                                        <i:InvokeCommandAction Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid}},
                                            Path=DataContext.StartCellCommand}"
                                            CommandParameter="{Binding CurrentCell, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}}" />
                                    </i:EventTrigger>
                                </i:Interaction.Triggers>
                            </TextBlock>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>

                </DataGridTemplateColumn>-->

                <DataGridTextColumn Header="5" MaxWidth="10" FontSize="8" Width="10" IsReadOnly="True">
                    <DataGridTextColumn.ElementStyle>
                        <Style TargetType="{x:Type TextBlock}">
                            <Setter Property="Background" Value="{Binding _5, Converter={StaticResource ResourceKey=hourSlotColorConverter}, UpdateSourceTrigger=PropertyChanged}"/>
                            <Setter Property="Margin" Value="-1" />
                        </Style>
                    </DataGridTextColumn.ElementStyle>
                </DataGridTextColumn>

                <DataGridTextColumn Header="" MaxWidth="10" IsReadOnly="True">
                    <DataGridTextColumn.ElementStyle>
                        <Style TargetType="{x:Type TextBlock}">
                            <Setter Property="Background" Value="{Binding _5_5, Converter={StaticResource ResourceKey=hourSlotColorConverter}, UpdateSourceTrigger=PropertyChanged}"/>
                            <Setter Property="Margin" Value="-1" />
                        </Style>
                    </DataGridTextColumn.ElementStyle>
                </DataGridTextColumn>

                <DataGridTextColumn Header="6" MaxWidth="10" IsReadOnly="True">
                    <DataGridTextColumn.ElementStyle>
                        <Style TargetType="{x:Type TextBlock}">
                            <Setter Property="Background" Value="{Binding _6, Converter={StaticResource ResourceKey=hourSlotColorConverter}, UpdateSourceTrigger=PropertyChanged}"/>
                            <Setter Property="Margin" Value="-1" />
                        </Style>
                    </DataGridTextColumn.ElementStyle>
                </DataGridTextColumn>

                <DataGridTextColumn Header="" MaxWidth="10" IsReadOnly="True" >
                    <DataGridTextColumn.ElementStyle>
                        <Style TargetType="{x:Type TextBlock}">
                            <Setter Property="Background" Value="{Binding _3_5, Converter={StaticResource ResourceKey=hourSlotColorConverter}, UpdateSourceTrigger=PropertyChanged}"/>
                            <Setter Property="Margin" Value="-1" />
                        </Style>
                    </DataGridTextColumn.ElementStyle>
                </DataGridTextColumn>

                <DataGridTextColumn Header="4" MaxWidth="10" IsReadOnly="True" >
                    <DataGridTextColumn.ElementStyle>
                        <Style TargetType="{x:Type TextBlock}">
                            <Setter Property="Background" Value="{Binding _4, Converter={StaticResource ResourceKey=hourSlotColorConverter}, UpdateSourceTrigger=PropertyChanged}"/>
                            <Setter Property="Margin" Value="-1" />
                        </Style>
                    </DataGridTextColumn.ElementStyle>
                </DataGridTextColumn>

                <DataGridTextColumn Header="" MaxWidth="9"  IsReadOnly="True">
                    <DataGridTextColumn.ElementStyle>
                        <Style TargetType="{x:Type TextBlock}">
                            <Setter Property="Background" Value="{Binding _4_5, Converter={StaticResource ResourceKey=hourSlotColorConverter}, UpdateSourceTrigger=PropertyChanged}"/>
                            <Setter Property="Margin" Value="-1" />
                        </Style>
                    </DataGridTextColumn.ElementStyle>
                </DataGridTextColumn>

            </DataGrid.Columns>
        </DataGrid>

    </Grid>


</UserControl>

the code-behind

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel.Composition;
using MainModule.Infrastructure.Interface;
using Widget5.ViewModel;

namespace Widget5.View
{
    /// <summary>
    /// Interaction logic for ExcelDisplay.xaml
    /// </summary>
    [Export(typeof(IMainModulePage))]
    [ExportMetadata("WidgetName", "Widget5")]
    [ExportMetadata("MenuNo", 1)]
    [ExportMetadata("PageTitle", "WorkItemsPage")]
    public partial class WorkItemsDisplay : UserControl, IMainModulePage
    {
        public WorkItemsDisplay()
        {
            DataContext = eVM;
            InitializeComponent();
        }

        // inherit
        public string WidgetName
        {
            get { return "Widget5"; }
        }

        public int MenuNo
        {
            get { return 1; }
        }

        public string PageTitle
        {
            get { return "WorkItemsPage"; }
        }

        ExcelGridViewModel eVM = new ExcelGridViewModel();
        bool isClicked;
        List<int> trueCells;
        bool hasMoved;

        private void ScheduleTable_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            DependencyObject dep = (DependencyObject)e.OriginalSource;

            // iteratively traverse the visual tree
            while ((dep != null) &&
                    !(dep is DataGridCell))
            {
                dep = VisualTreeHelper.GetParent(dep);
            }

            if (dep == null)
                return;

            if (dep is DataGridCell)
            {
                DataGridCell cell = dep as DataGridCell;
                DataGridCellInfo cellInfo = new DataGridCellInfo(cell);

                while ((dep != null) && !(dep is DataGridRow))
                {
                    dep = VisualTreeHelper.GetParent(dep);
                }

                DataGridRow row = dep as DataGridRow;

                hasMoved = false;

                if (eVM.DoEndCell(cell, row, hasMoved))
                    ScheduleDG.UnselectAllCells();
                ScheduleDG.CurrentCell = cellInfo;

            }

            isClicked = false;

        }

        private void ScheduleTable_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            DependencyObject dep = (DependencyObject)e.OriginalSource;


            // iteratively traverse the visual tree
            while ((dep != null) &&
                    !(dep is DataGridCell))
            {
                dep = VisualTreeHelper.GetParent(dep);
            }

            if (dep == null)
                return;

            if (dep is DataGridCell)
            {
                DataGridCell cell = dep as DataGridCell;

                while ((dep != null) && !(dep is DataGridRow))
                {
                    dep = VisualTreeHelper.GetParent(dep);
                }

                DataGridRow row = dep as DataGridRow;

                trueCells = eVM.DoStartCell(cell, row);
            }

            isClicked = true;
        }

        private void Grid_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
        {
            e.Handled = true;
        }

        private void ScheduleDG_MouseMove(object sender, MouseEventArgs e)
        {
            DependencyObject dep = (DependencyObject)e.OriginalSource;

            // iteratively traverse the visual tree
            while ((dep != null) &&
                    !(dep is DataGridCell))
            {
                dep = VisualTreeHelper.GetParent(dep);
            }

            if (dep == null)
                return;

            if (dep is DataGridCell)
            {
                DataGridCell cell = dep as DataGridCell;
                DataGridCellInfo cellInfo = new DataGridCellInfo(cell);

                while ((dep != null) && !(dep is DataGridRow))
                {
                    dep = VisualTreeHelper.GetParent(dep);
                }

                DataGridRow row = dep as DataGridRow;

                if (isClicked && (trueCells.Count <= 1))
                {
                    hasMoved = true;
                    eVM.DoEndCell(cell, row, hasMoved);
                }
            }
        }

        private void Grid_MouseUp(object sender, MouseButtonEventArgs e)
        {
            isClicked = false;
            hasMoved = false;
        }


    }
}

EDIT

I proceeded to multibind the datagridcell's column and datacontext properties as parameters for my command. An option I started before but set aside due to time constraints. Instead of looking for the datagridrow's index, I used the datacontext to compare to my viewmodel. Did the trick.

ciscoheat
  • 3,719
  • 1
  • 35
  • 52
eemwingg
  • 15
  • 7

2 Answers2

1

The general way to achieve your requirement is to implement an ICommand type Attached Property for each event that you want to replace. The basic idea is this... add an ICommand Attached Property with a PropertyChangedCallback handler. In this handler (which will be called when an ICommand is data bound to this property), attach a handler to the event that you want to handle. Then, when that event is called, just execute the ICommand instance. So you can handle the event in your view model via the ICommand instance. Here is an example using the PreviewKeyDown event:

public static DependencyProperty OnEnterKeyDownProperty = DependencyProperty.RegisterAttached("OnEnterKeyDown", typeof(ICommand), typeof(TextBoxProperties), new UIPropertyMetadata(null, OnOnEnterKeyDownChanged));

public static ICommand GetOnEnterKeyDown(DependencyObject dependencyObject)
{
    return (ICommand)dependencyObject.GetValue(OnEnterKeyDownProperty);
}

public static void SetOnEnterKeyDown(DependencyObject dependencyObject, ICommand value)
{
    dependencyObject.SetValue(OnEnterKeyDownProperty, value);
}

public static void OnOnEnterKeyDownChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
    TextBox textBox = dependencyObject as TextBox;
    if (e.OldValue == null && e.NewValue != null) textBox.PreviewKeyDown += TextBox_OnEnterKeyDown;
    else if (e.OldValue != null && e.NewValue == null) textBox.PreviewKeyDown -= TextBox_OnEnterKeyDown;
}

private static void TextBox_OnEnterKeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Enter || e.Key == Key.Return)
    {
        TextBox textBox = sender as TextBox;
        ICommand command = GetOnEnterKeyDown(textBox);
        if (command != null && command.CanExecute(textBox)) command.Execute(textBox);
    }
    e.Handled = false;
}
Sheridan
  • 68,826
  • 24
  • 143
  • 183
  • +1 Commands are also a good idea. I completely forgot about them. :) – dev hedgehog Nov 29 '13 at 11:12
  • @Sheridan I have also tried using Icommand for this. I forgot what made me drop it but I'm sure something went wrong so I used my solution above. Say, I already added ICommand properties on my viewmodel. – eemwingg Dec 02 '13 at 02:13
  • I am sorry I do not know how to format this correctly. Anyway, that is the part in my XAML that is supposed to trigger. Why doesn't the ICommand get called? – eemwingg Dec 02 '13 at 02:14
  • When adding code, *always* add it to the end of your question in an edit because it's just too hard to see it properly in the comments. – Sheridan Dec 02 '13 at 09:03
  • Ok noted sir. As of now, I reverted to using commands and opted to use multibinding on my command parameters. However, I have 48 cells that contain the same triggers, which is very redundant. Is there anyway to make a template for the triggers inside a textblock? Codes are here [link](http://stackoverflow.com/questions/20368667/datagridtemplatecolumn-invokecommandaction-template) – eemwingg Dec 05 '13 at 09:31
0

Alternative would be to work with properties DataGrid already provides to you and/or to define few other attached properties supporting you to get the job done.

I would try to work with properties like SelectedItem, SelectedValue, CurrentItem, CurrentCell.

Futhermore if a behavior couldnt be handled with those properties from above I would create an attached property and use a style for cells with triggers changing the attached property. Binding will transmit all the changes from the attached property to the ViewModel.

In the end you will have just communication between ViewModel and View.

Here are few links:

http://msdn.microsoft.com/en-us/library/system.windows.controls.datagrid%28v=vs.110%29.aspx

http://msdn.microsoft.com/en-us/library/system.windows.controls.datagrid.currentitem%28v=vs.110%29.aspx

http://msdn.microsoft.com/en-us/library/system.windows.controls.primitives.selector.selectedvalue%28v=vs.110%29.aspx

http://msdn.microsoft.com/en-us/library/system.windows.controls.primitives.selector.selecteditem%28v=vs.110%29.aspx

They should be all bindable

Edit:

Link to MSDN MultiBinding Page:

http://msdn.microsoft.com/en-us/library/system.windows.data.multibinding%28v=vs.110%29.aspx

dev hedgehog
  • 8,698
  • 3
  • 28
  • 55
  • Hi! Thanks for replying. Yes I was able to investigate all the properties you've listed. It sucks how the CurrentCell only contains information on the cell's column index and does not include the row. As for the other properties, none of them fit the criteria as well. – eemwingg Nov 29 '13 at 10:50
  • How come none of the fits? You could bind to SelectedItem. When a cell is being clicked it will be selected and so you will know in your ViewModel which item is being currently used. Futhermore when user starts editing the cell you will get changes permitted to a certain property in ViewModel and so you can do custom logic when property changed... Its just an idea. You need to be creative with those properties I listed to you. Some of them need additional attached property to fullfill the desired behavior. :) – dev hedgehog Nov 29 '13 at 11:09
  • Create a style for cells with trigger transfering the value from CurrentCell to some attached property which futhermore will be bound to ViewModel. Be creative like that... Attached properties are bindable. – dev hedgehog Nov 29 '13 at 11:11
  • I'm sorry, I forgot to tell you that I am not that well-versed in this as I have only been using c# for a few months, moreso, use the MVVM pattern. – eemwingg Dec 02 '13 at 01:40
  • I revised my code to the following. CommandParameter="{Binding Path=Column, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGridCell}}" I am able to get the cell's column index, however, I also need to get the row index. Your help will be greatly appreciated. – eemwingg Dec 02 '13 at 07:17
  • Use MultiBinding. One Binding binds to AncestorType DataGridCell another binds to AncestorType DataGridRow. :) – dev hedgehog Dec 02 '13 at 07:23
  • - yes I am into that sir. as I was reading, I can not find any concrete or even just similar codes. Could you help me with a snippet for this? Thanks in advance! – eemwingg Dec 02 '13 at 07:39
  • I will provide you with links that contain code: http://blog.csainty.com/2009/12/wpf-multibinding-and.html and this one is pretty good too http://msdn.microsoft.com/en-us/library/system.windows.data.multibinding%28v=vs.110%29.aspx – dev hedgehog Dec 02 '13 at 07:47
  • I prayed like hell and I think I'm on the right track! Hahaha. I already thought of doing multibindings before but thought that my previous solution was easier. If not for my project leader, I would just have stuck to it. Thanks for all your help! – eemwingg Dec 02 '13 at 08:42