Your Privacy Matters: We use our own and third-party cookies to improve your experience on our website. By continuing to use the website we understand that you accept their use. Cookie Policy
340
Customize XamDataGrid RecordSelector
posted

Hi Team,

Requirement: Only check boxes are allowed for selection. When user single click on the row in the grid, it should not change the selected status of the checkbox. If the user double click, we can consider launching the details for the row.

I'm using XamDataGrid RecordSelector to display check box to select the item. But I'm not able to achieve this behavior. I want to fire view model command on row double click and want to pass the clicked row. But I don't want to make clicked row as selected. I’m able to fire view model command but not able to pass the clicked row object. I'm getting it as null. Please find below XAML and grid behavior.

Can you please help me to achieve this behavior?

XAML:

<Style TargetType="{x:Type igDP:RecordSelector}" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type igDP:RecordSelector}">
<CheckBox 
HorizontalAlignment="Center"
VerticalAlignment="Center"
Loaded="Item_CheckBox_OnLoaded"
Checked="Item_CheckBox_Checked"
Unchecked="Item_CheckBox_Unchecked"
IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Record.IsSelected, Mode=TwoWay}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type igDP:HeaderPrefixArea}" BasedOn="{x:Null}">
<Setter Property="Visibility" Value="Visible" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type igDP:HeaderPrefixArea}">
<CheckBox 
HorizontalAlignment="Center"
VerticalAlignment="Center" 
Loaded="Header_CheckBox_Loaded"
Checked="Header_CheckBox_Checked"
Unchecked="Header_CheckBox_Unchecked" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

 

<i:Interaction.Behaviors>
<behaviors:XamDataGridBehavior SelectedItems="{Binding SelectedUsers, Mode=TwoWay}"></behaviors:XamDataGridBehavior>
</i:Interaction.Behaviors>

 

<!--<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<i:InvokeCommandAction Command="{Binding Path=DataContext.ViewCommand, RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type Window}}}" CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=Parent.PlacementTarget.Record}" />
</i:EventTrigger>
</i:Interaction.Triggers>-->
<igDP:XamDataGrid.InputBindings>
<!--<MouseBinding MouseAction="LeftDoubleClick" Command="{Binding Path=DataContext.ViewCommand, RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type Window}}}" CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=Parent.PlacementTarget.Record}"/>-->
<!--<KeyBinding Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.KeyDownCommand}" Key="Space"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type igDP:XamDataGrid}}, Path=ActiveDataItem}"/>
Header="Menu Item 1" CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=Parent.PlacementTarget.Record}"
CommandParameter="{Binding Path=DataItem}"-->

 

XAML.cs

 

private void Header_CheckBox_Loaded(object sender, RoutedEventArgs e)
{
      userHeaderCheckBox = (CheckBox)sender;
}

private void Header_CheckBox_Checked(object sender, RoutedEventArgs e)
{
DataRecordPresenter r = Utilities.GetAncestorFromType(sender as DependencyObject, typeof(DataRecordPresenter), false) as DataRecordPresenter;

SetSelection(r, true);
}

private void Header_CheckBox_Unchecked(object sender, RoutedEventArgs e)
{
DataRecordPresenter r = Utilities.GetAncestorFromType(sender as DependencyObject, typeof(DataRecordPresenter), false) as DataRecordPresenter;

SetSelection(r, false);
}

void SetSelection(DataRecordPresenter r, bool operation)
{
var currentUsers = r.Record.RecordManager.GetFilteredInDataRecords().Any() ? 
r.Record.RecordManager.GetFilteredInDataRecords() : (IEnumerable<Record>)r.Record.RecordManager.Current;

foreach (Record rec in currentUsers)
{
rec.IsSelected = operation;
}
}

private void Item_CheckBox_Checked(object sender, RoutedEventArgs e)
{
DataRecordPresenter r = Utilities.GetAncestorFromType(sender as DependencyObject, typeof(DataRecordPresenter), false) as DataRecordPresenter;
if (r != null)
{
if (AreAllRecordsSelected(r.Record as DataRecord) && _userHeaderCheckBox.IsChecked == false)
{
_userHeaderCheckBox.Checked -= Header_CheckBox_Checked;
_userHeaderCheckBox.IsChecked = true;
_userHeaderCheckBox.Checked += Header_CheckBox_Checked;
}
}
}

private void Item_CheckBox_Unchecked(object sender, RoutedEventArgs e)
{
if (usersHeaderCheckBox.IsChecked == true)
{
usersHeaderCheckBox.Unchecked -= Header_CheckBox_Unchecked;
usersHeaderCheckBox.IsChecked = false;
usersHeaderCheckBox.Unchecked += Header_CheckBox_Unchecked;
}
}

public bool AreAllRecordsSelected(DataRecord r)
{
var currentUsers = r.DataPresenter.RecordManager.GetFilteredInDataRecords().Any() ?
r.DataPresenter.RecordManager.GetFilteredInDataRecords() : (IEnumerable<Record>)r.DataPresenter.RecordManager.Current;

return currentUsers.All(rec => rec.IsSelected);
}

private void Item_CheckBox_OnLoaded(object sender, RoutedEventArgs e)
{
if (sender is CheckBox)
{
((CheckBox)sender).Checked += Item_CheckBox_Checked;
((CheckBox)sender).Unchecked += Item_CheckBox_Unchecked;
}
}

 

Attaching XamDataGridBehavior.

Thanks in advance.

 

XamDataGridBehavior.txt
public class XamDataGridBehavior : Behavior<XamDataGrid>
    {
        // Source: The XamDataGrid's SelectedRows collection
        // Target: The object bound as the behaviors SelectedItems collection


        private XamDataGrid Grid
        {
            get
            {
                return AssociatedObject as XamDataGrid;
            }
        }

        public INotifyCollectionChanged SelectedItems
        {
            get { return (INotifyCollectionChanged)GetValue(SelectedItemsProperty); }
            set { SetValue(SelectedItemsProperty, value); }
        }

        public static readonly DependencyProperty SelectedItemsProperty = DependencyProperty.Register(
            "SelectedItems",
            typeof(INotifyCollectionChanged),
            typeof(XamDataGridBehavior),
            new PropertyMetadata(new ObservableCollection<object>()));
        


        // Using a DependencyProperty as the backing store for SelectedActiveItems.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SelectedActiveItemProperty =
            DependencyProperty.Register("SelectedActiveItem", typeof(object), typeof(XamDataGridBehavior), new PropertyMetadata(0));


        public object SelectedActiveItem
        {
            get { return GetValue(SelectedActiveItemProperty); }
            set { SetValue(SelectedActiveItemProperty, value); }
        }

        protected override void OnAttached()
        {
            base.OnAttached();

            Grid.SelectedItemsChanged += Grid_SelectedItemsChanged;
            Grid.Loaded += Grid_Loaded;
            Grid.CellActivated += Grid_CellActivated;
            Grid.RecordActivating += Grid_RecordActivating;
            Grid.MouseDoubleClick += Grid_MouseDoubleClick;
        }

        private void Grid_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (sender is DataRecord)
            {

            }
            else if (sender is Record)
            {

            }
        }

        void Grid_RecordActivating(object sender, RecordActivatingEventArgs e)
        {
            e.Cancel = true;
        }

        void Grid_CellActivated(object sender, CellActivatedEventArgs e)
        {
            var activeRecord = (sender as XamDataGrid).ActiveRecord;
            var dataItem = ((DataRecord)activeRecord).DataItem;
            SelectedActiveItem = dataItem;
        }

        void Grid_Loaded(object sender, RoutedEventArgs e)
        {
            SelectedItems.CollectionChanged += SelectedItems_CollectionChanged;
        }

        void Grid_SelectedItemsChanged(object sender, SelectedItemsChangedEventArgs e)
        {
            UnsubscribeFromEvents();

            TransferSourceToTarget(Grid.SelectedItems.Records, SelectedItems as IList);

            SubscribeToEvents();
        }

        void SelectedItems_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            UnsubscribeFromEvents();

            TransferTargetToSource(SelectedItems as IList, Grid);

            SubscribeToEvents();
        }

        private void SubscribeToEvents()
        {
            Grid.SelectedItemsChanged += Grid_SelectedItemsChanged;
            SelectedItems.CollectionChanged += SelectedItems_CollectionChanged;
        }

        private void UnsubscribeFromEvents()
        {
            Grid.SelectedItemsChanged -= Grid_SelectedItemsChanged;
            SelectedItems.CollectionChanged -= SelectedItems_CollectionChanged;
        }

        public static void TransferSourceToTarget(SelectedItemCollectionBase source, IList target)
        {
            if (source == null || target == null)
                return;

            target.Clear();

            foreach (Record r in source)
            {
                // make sure we only take data rows from the root band
                if (r.IsDataRecord && r.ParentRecord == null)
                {
                    target.Add((r as DataRecord).DataItem);
                }
            }
        }

        public static void TransferTargetToSource(IList target, XamDataGrid source)
        {
            if (source == null || target == null)
                return;
   
            source.SelectedItems.Records.Clear();

            foreach (object obj in target)
            {
                foreach (Record record in source.Records)
                {

                    if ((record as DataRecord).DataItem.Equals(obj))
                    {
                        source.SelectedItems.Records.Add(record);
                    }
                }
            }

            // If selected items is still empty then we don't have an active record anymore.
            //if (source.SelectedItems.Records.Count == 0)
            //    source.ActiveRecord = null;
        }
    }

  • 26865
    Offline posted

    Hello, 

    You wish to double click a row but not make it selected? That is not how the grid behaves. You could always hook SelectedItemsChanging, get the Record that is selected, and cancel it.