Ramji
Ramji

Reputation: 43

How to enable and disable dynamic context menu based on condition in DataGrid?

I am using the ContextMenu in WPF, it shows send and resend MenuItem in the ContextMenu. How can I use the Send and Resend menu items in the code below to enable/disable the context menu?

<DataGrid.ContextMenu>
    <ContextMenu x:Name="CMenuu"> 
        <MenuItem Name="Send" Header="Send" Click="Send_Click"/>
        <MenuItem Name="Resend" Header="Resend" Click="Resend_Click"/>
        <MenuItem Name="Report"Header="Report" Click="Report_Click"/>
    </ContextMenu>
</DataGrid.ContextMenu>

Upvotes: 0

Views: 4991

Answers (2)

Ashok Rathod
Ashok Rathod

Reputation: 840

Please Find Here My Sample solution to achieve this functionality by adding contextmenu item and its enable/disable doing in code behind. Its fully tested and serves your functionality.

I am pasting here full sample code here

Mainwindow.xaml

<Window x:Class="yourapplicatioName.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 x:Name="data1" AutoGenerateColumns="True"  ItemsSource="{Binding Path=.}"  Width="500" Height="500" PreviewMouseRightButtonDown="data1_PreviewMouseRightButtonDown_1">
            </DataGrid>

    </Grid>
</Window>

Mainwindow.xaml.cs

public MainWindow()
        {
            InitializeComponent();
            BindDataToDataGrid();
        }


        private void Send_Click_1(object sender, RoutedEventArgs e)
        {

        }

        private void Resend_Click_1(object sender, RoutedEventArgs e)
        {

        }

        private void Report_Click_1(object sender, RoutedEventArgs e)
        {

        }

        public static T FindVisualParent<T>(UIElement element) where T : UIElement
        {
            UIElement parent = element;
            while (parent != null)
            {
                T correctlyTyped = parent as T;
                if (correctlyTyped != null)
                {
                    return correctlyTyped;
                }
                parent = VisualTreeHelper.GetParent(parent) as UIElement;
            }
            return null;
        }

        private void BindDataToDataGrid()
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("ID");
            dt.Columns.Add("StatusCode");
            dt.Rows.Add("Kartik", "Send");
            dt.Rows.Add("Ashok", "Resend");
            dt.Rows.Add("Paresh", "Report");
            dt.AcceptChanges();

            data1.ItemsSource = dt.DefaultView;
        }

        private void data1_PreviewMouseRightButtonDown_1(object sender, MouseButtonEventArgs e)
        {
            if (e.OriginalSource.GetType() != typeof(DataGridColumnHeader))
            {
                DataGridRow dgr = FindVisualParent<DataGridRow>(e.OriginalSource as UIElement);
                if (dgr != null && dgr.Item != null)
                {
                    //here checked value of statuscode on the basis of row clicked
                    string statusCode = Convert.ToString((dgr.Item as DataRowView).Row["StatusCode"]);

                    if (statusCode == "Send")
                    {
                        MenuItem objResend = new MenuItem();
                        objResend.Header = "Resend";
                        objResend.Click += Resend_Click_1;

                        MenuItem objsend = new MenuItem();
                        objsend.Header= "Send";
                        objsend.IsEnabled = false;

                        data1.ContextMenu = new System.Windows.Controls.ContextMenu();

                        data1.ContextMenu.Items.Add(objResend);
                        data1.ContextMenu.Items.Add(objsend);
                    }
                    else if (statusCode == "Resend")
                    {
                        //on resend resend is disabled
                        MenuItem objResend = new MenuItem();
                        objResend.Header = "Resend";
                        objResend.IsEnabled = false;

                        MenuItem objsend = new MenuItem();
                        objsend.Header = "Send";
                        objsend.Click += Send_Click_1;

                        data1.ContextMenu = new System.Windows.Controls.ContextMenu();
                        data1.ContextMenu.Items.Add(objResend);
                        data1.ContextMenu.Items.Add(objsend);
                    }
                    else if (statusCode == "Report")
                    {
                        //both are enabled 
                        MenuItem objResend = new MenuItem();
                        objResend.Header = "Resend";
                        objResend.Click += Resend_Click_1;

                        MenuItem objsend = new MenuItem();
                        objsend.Header = "Send";
                        objsend.Click += Send_Click_1;

                        data1.ContextMenu = new System.Windows.Controls.ContextMenu();
                        data1.ContextMenu.Items.Add(objResend);
                        data1.ContextMenu.Items.Add(objsend);
                    }
                }
            }
        }

Here i have handled contextmenu opening in right button click on datagridrow. you can change it to any mouse event e.g previewmousebuttondown, previewmouserightbuttondown.. u just need to do relevant change in xaml for handling specific event.

Please mark it as solution .. if it really helps you. if any query or doubt. Please let me know

Just create new functionality and add above xaml and xaml.cs in your respective files and you will get better idea what this code actually doing

Above code is feasible when you have only less no of contextmenu items.Its not advisable to do above code when menuitems are more.

Find Working Code Result in Images at below Shared Skydrive location : http://1drv.ms/1sJF6WQ

Upvotes: 2

InvisiblePanda
InvisiblePanda

Reputation: 1609

I'll post this as an answer since you asked in the hope that the code might work as is, but I don't have the means of testing right now. I'll check back later and correct accordingly if it shouldn't. The simplest (though not MVVM-respecting, if you're using that) way would be to do the following in the Click handler of the MenuItem:

private void Send_Click(object sender, RoutedEventArgs e)
{
  Send.IsEnabled = false;
  Resend.IsEnabled = true;
}

and

private void Resend_Click(object sender, RoutedEventArgs e)
{
  Send.IsEnabled = true;
  Resend.IsEnabled = false;
}

This is "quick and dirty" though, and you should add the following to the XAML Markup if you don't want both menu items to be enabled at the start:

<MenuItem Name="Resend" Header="Resend" Click="Resend_Click" IsEnabled="False"/>

Hope this helps a bit and I understood you correctly.

Edit: It seems something else was wished for. I hope I got it this time. You could add a handler for the Opened event in the ContextMenu definition, e.g.

<ContextMenu x:Name="cMenuu" Opened="cMenuu_Opened"> ...

Then do something along the lines of the following (since you didn't give the code for the status stuff, I can only guess here):

private void cMenuu_Opened(object sender, RoutedEventArgs e)
{
  // Here, get the selected item from your grid and check the status
  var item = yourGridNameHere.SelectedItem;

  // Again: pseudo code to check the status
  if (item.Status == "reported")
  {
    Send.IsEnabled = false;
    Resend.IsEnabled = true;
  }
  else
  {
    // Something else, like enable the other menu items again
  }
}

Upvotes: 0

Related Questions