ডাব্লুপিএফ ডেটাগ্রিডে সিঙ্গল ক্লিক চেকবক্স নির্বাচন কীভাবে সম্পাদন করবেন?


143

আমার কাছে পাঠ্য কলাম হিসাবে প্রথম কলাম এবং চেকবক্স কলাম হিসাবে দ্বিতীয় কলাম সহ একটি ডেটাগ্রিড রয়েছে। আমি যা চাই তা হ'ল, যদি আমি চেক বাক্সে ক্লিক করি। এটি চেক করা উচিত।

তবে, নির্বাচিত হতে দু'বার ক্লিক লাগে, প্রথম ক্লিকের জন্য সেলটি নির্বাচিত হচ্ছে, দ্বিতীয় ক্লিকের জন্য চেক বক্সটি চেক করা হচ্ছে। একক ক্লিকের সাহায্যে চেক বক্সটি কীভাবে চেক / চেক করা যায় না।

আমি ডাব্লুপিএফ ৪.০ ব্যবহার করছি। ডেটাগ্রিডে কলামগুলি অটো জেনারেটেড।


4
সদৃশ: stackoverflow.com/questions/1225836/... , কিন্তু এই এক ভাল টাইটেল দিয়েছেন
surfen

উত্তর:


189

একক ক্লিকের জন্য ডেটাগ্রিড চেকবক্স আপনি কেবল নিয়মিত চেকবক্স নিয়ন্ত্রণ ভিতরে রেখে DataGridTemplateColumnসেট করতে পারেন UpdateSourceTrigger=PropertyChanged

<DataGridTemplateColumn.CellTemplate>
    <DataTemplate>
        <CheckBox IsChecked="{Binding Path=IsSelected, UpdateSourceTrigger=PropertyChanged}" />
    </DataTemplate>
</DataGridTemplateColumn.CellTemplate>

4
বাহ - আমি শেষ পর্যন্ত পড়ে খুশি glad এটি নিখুঁতভাবে কাজ করে এবং যথেষ্ট কম জটিল, আইএমও এটি উত্তর হিসাবে চিহ্নিত করা উচিত।
টড

2
এটি কম্বোবক্সের জন্যও কাজ করে। যেমন হিসাবে: ওয়ে, ডেটাগ্রিডকমবো বক্সস কলামের চেয়ে ভাল।
ব্যবহারকারী1454265

2
যখন আমি স্পেস বারটি ব্যবহার করি / চেক করতে বাছাই করতে এবং অন্য একটি ঘরে চলে যেতে তীরগুলি ত্যাগ করে doesn't
ইওলা

1
আমি এই উত্তরটি ব্যাখ্যা করেছি যে আপনাকে "ইসসলেক্টেড" বাঁধতে হবে, তবে এটি সত্য নয়! আপনি কেবল আপনার নিজের বাঁধাইয়েরDataGridTemplateColumn.CellTemplate সাথে ব্যবহার করতে পারেন এবং এটি কার্যকর হবে! @ ওয়েডিয়ান-হুয়াংয়ের উত্তর আমাকে তা বুঝতে সাহায্য করেছে, ধন্যবাদ!
অ্যাস্ট্রালিসসোনিয়াম

62

আমি নিম্নলিখিত স্টাইল দিয়ে এটি সমাধান:

<Style TargetType="DataGridCell">
     <Style.Triggers>
         <Trigger Property="IsMouseOver" Value="True">
             <Setter Property="IsEditing" Value="True" />
         </Trigger>
     </Style.Triggers>
 </Style>

এটি অবশ্যই নির্দিষ্ট কলামগুলির জন্য আরও খাপ খাইয়ে নেওয়া সম্ভব ...


8
খুশী হলাম। আমি এটিকে একটি মাল্টিট্রিগারে পরিবর্তন করেছি এবং ReadOnly = মিথ্যা জন্য একটি শর্ত যুক্ত করেছি তবে মূল পদ্ধতিটি আমার সাধারণ ক্ষেত্রে কাজ করে যেখানে কীবোর্ড নেভিগেশন গুরুত্বপূর্ণ নয়।
18:25

আমার গ্রিডে সেই স্টাইল যুক্ত করা অপারেশন ব্যতিক্রম বাড়াতে বৈধ নয় যখন আইটেমসোর্স ব্যবহৃত হয়। পরিবর্তে আইটেমসন্ট্রোল.আইটেমসোর্স সহ উপাদানগুলিতে অ্যাক্সেস এবং সংশোধন করুন।
অ্যালক্যাম্পার

1
এটি এ পর্যন্ত দেখা সবচেয়ে পরিষ্কার উপায়! নিস! (ইসআরেডঅনলি জন্য = "সত্য" একটি মাল্টি ট্রিজার কাজটি করবে)
FooBarTheLittle

2
এই সমাধানটির কিছু অপ্রত্যাশিত / অযাচিত আচরণ রয়েছে। দেখুন stackoverflow.com/q/39004317/2881450
jHilscher

2
কাজ করার জন্য বাইন্ডিংয়ের জন্য আপনার প্রয়োজন আপডেটসোর্সটি ট্রিগার = প্রপার্টি
চেঞ্জড

27

প্রথমত, আমি জানি এটি একটি পুরানো প্রশ্ন তবে আমি এখনও ভেবেছিলাম চেষ্টা করে উত্তর দিয়ে দেব।

কয়েক দিন আগেও আমার একই সমস্যা ছিল এবং এর জন্য একটি আশ্চর্যজনক সংক্ষিপ্ত সমাধানটি পেলাম ( এই ব্লগটি দেখুন )। মূলত, আপনাকে যা করতে হবে তা হ'ল DataGridCheckBoxColumnআপনার এক্সএএমএল-এর সংজ্ঞাটি নীচের সাথে প্রতিস্থাপন করুন :

<DataGridTemplateColumn Header="MyCheckBoxColumnHeader">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <CheckBox HorizontalAlignment="Center" VerticalAlignment="Center" IsChecked="{Binding Path=MyViewModelProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

এই সমাধানটির উল্টো দিকটি স্পষ্ট - এটি এক্সএএমএল-কেবল; সুতরাং এটি অতিরিক্ত ইউআই যুক্তি দিয়ে আপনার কোড-ব্যাকে বোঝা করা থেকে কার্যকরভাবে বিরত থাকে এবং আপনাকে এমভিভিএম জেলিওল্টের দৃষ্টিতে আপনার স্ট্যাটাস বজায় রাখতে সহায়তা করে;)।


1
এটি কনস্ট্যান্টিন সালাভাতভের উত্তরের মতো এবং এটি আমার পক্ষে কাজ করেছিল। কোড নমুনা যেখানে নেই সেগুলি অন্তর্ভুক্ত করার জন্য +1। একটি পুরানো প্রশ্নের উত্তরের জন্য ধন্যবাদ।
ডন হেরোড

1
এর সাথে সমস্যা হ'ল আপনি যদি এটি কম্বোবক্স কলামগুলির সাথে করেন তবে ছোট ড্রপডাউন বোতামটি সেই কলামের সমস্ত কক্ষের জন্য, সমস্ত সময় দৃশ্যমান হবে। আপনি যখন ঘরে ক্লিক করেন ঠিক তখনই।
ব্যবহারকারী 3690202

18

করতে কনস্টানটিন Salavatov এর উত্তর দিয়ে কাজ AutoGenerateColumns, এর একটি ইভেন্ট হ্যান্ডলার যোগ DataGrid'র AutoGeneratingColumnনিম্নলিখিত কোড সহ:

if (e.Column is DataGridCheckBoxColumn && !e.Column.IsReadOnly)
{
    var checkboxFactory = new FrameworkElementFactory(typeof(CheckBox));
    checkboxFactory.SetValue(FrameworkElement.HorizontalAlignmentProperty, HorizontalAlignment.Center);
    checkboxFactory.SetValue(FrameworkElement.VerticalAlignmentProperty, VerticalAlignment.Center);
    checkboxFactory.SetBinding(ToggleButton.IsCheckedProperty, new Binding(e.PropertyName) { UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });

    e.Column = new DataGridTemplateColumn
        {
            Header = e.Column.Header,
            CellTemplate = new DataTemplate { VisualTree = checkboxFactory },
            SortMemberPath = e.Column.SortMemberPath
        };
}

এটি সমস্ত DataGridস্বয়ংক্রিয়ভাবে উত্পাদিত চেকবক্স কলামগুলিকে "একক ক্লিক" সম্পাদনযোগ্য করে তুলবে ।


একটি স্বয়ংক্রিয় জেনারেটেড কলাম পদ্ধতির পূরণ করার জন্য ধন্যবাদ, এটি আমাকে সহজেই একটি উপযুক্ত দিক নির্দেশ করে।
el2iot2

17

গোব্লিনের উত্তরে রেফারেন্সযুক্ত ব্লগের ভিত্তিতে, তবে। নেট 4.0 এবং সারি-নির্বাচন মোডের সাথে কাজ করতে সংশোধিত।

লক্ষ্য করুন যে এটি ডেটাগ্রিডকমবো বক্সস কলাম সম্পাদনাও গতিবেগ করে - সম্পাদনা মোডে প্রবেশ করে এবং একক ক্লিক বা পাঠ্য ইনপুটটিতে ড্রপডাউন প্রদর্শন করে।

XAML:

        <Style TargetType="{x:Type DataGridCell}">
            <EventSetter Event="PreviewMouseLeftButtonDown" Handler="DataGridCell_PreviewMouseLeftButtonDown" />
            <EventSetter Event="PreviewTextInput" Handler="DataGridCell_PreviewTextInput" />
        </Style>

কোড-পিছনে:

    private void DataGridCell_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        DataGridCell cell = sender as DataGridCell;
        GridColumnFastEdit(cell, e);
    }

    private void DataGridCell_PreviewTextInput(object sender, TextCompositionEventArgs e)
    {
        DataGridCell cell = sender as DataGridCell;
        GridColumnFastEdit(cell, e);
    }

    private static void GridColumnFastEdit(DataGridCell cell, RoutedEventArgs e)
    {
        if (cell == null || cell.IsEditing || cell.IsReadOnly)
            return;

        DataGrid dataGrid = FindVisualParent<DataGrid>(cell);
        if (dataGrid == null)
            return;

        if (!cell.IsFocused)
        {
            cell.Focus();
        }

        if (cell.Content is CheckBox)
        {
            if (dataGrid.SelectionUnit != DataGridSelectionUnit.FullRow)
            {
                if (!cell.IsSelected)
                    cell.IsSelected = true;
            }
            else
            {
                DataGridRow row = FindVisualParent<DataGridRow>(cell);
                if (row != null && !row.IsSelected)
                {
                    row.IsSelected = true;
                }
            }
        }
        else
        {
            ComboBox cb = cell.Content as ComboBox;
            if (cb != null)
            {
                //DataGrid dataGrid = FindVisualParent<DataGrid>(cell);
                dataGrid.BeginEdit(e);
                cell.Dispatcher.Invoke(
                 DispatcherPriority.Background,
                 new Action(delegate { }));
                cb.IsDropDownOpen = true;
            }
        }
    }


    private 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;
    }

এই সমাধানটি আমার পক্ষে সবচেয়ে ভাল কাজ করেছে। আমার সীমাবদ্ধ ভিউমোডেল অন্যান্য সমাধানগুলির সাথে আপডেট হচ্ছে না।
ব্রোকমাইলগাইকিং

@ সুরফেন, আমার কি প্রতিটি পৃষ্ঠা এবং এর কোডবিহিনে উপরের স্টাইল এবং কোডটি লাগানো দরকার, যদি আমার অনেক পৃষ্ঠাতে এটিতে ডেটাগ্রিড থাকে তবে এটি তৈরি করার পরিবর্তে শৈলী এবং কোড কোনও সাধারণ জায়গায় ব্যবহার করা সম্ভব? প্রতিটি পৃষ্ঠা
অ্যাঞ্জেল

আপনাকে খালি অ্যাকশন প্রেরণের দরকার কেন?
ব্যবহারকারী 3690202

@ user3690202 এটি উইন্ডোজ.ফর্মগুলিতে ডওভেন্টসের মতো। বিগিনেডিট কল করার পরে আপনার সম্পাদনা মোডে প্রবেশের জন্য ঘরের জন্য অপেক্ষা করতে হবে।
জিří স্কলা 10

@ জিৎস্কিলা - আমার সমস্যার সমাধানের ক্ষেত্রে আমার এটি করার দরকার মনে পড়েনি, তবে আপনি কী বলছেন তা আমি বুঝতে পেরেছি - ধন্যবাদ!
ব্যবহারকারী 3690202

10

আমি এই পরামর্শগুলি এবং অন্যান্য সাইটগুলিতে প্রচুর পরিমাণে খুঁজে পেয়েছি, কিন্তু সেগুলির কোনওোটাই আমার পক্ষে যথেষ্ট কাজ করেন নি। শেষ পর্যন্ত আমি নিম্নলিখিত সমাধানটি তৈরি করেছিলাম।

আমি আমার নিজস্ব ডেটাগ্রিড-উত্তরাধিকারসূত্রে নিয়ন্ত্রণ তৈরি করেছি এবং কেবল এই কোডটিতে এটি যুক্ত করেছি:

public class DataGridWithNavigation : Microsoft.Windows.Controls.DataGrid
{
    public DataGridWithNavigation()
    {
        EventManager.RegisterClassHandler(typeof(DataGridCell), 
            DataGridCell.PreviewMouseLeftButtonDownEvent,
            new RoutedEventHandler(this.OnPreviewMouseLeftButtonDown));
    }


    private void OnPreviewMouseLeftButtonDown(object sender, RoutedEventArgs e)
    {
        DataGridCell cell = sender as DataGridCell;
        if (cell != null && !cell.IsEditing && !cell.IsReadOnly)
        {
          DependencyObject obj = FindFirstControlInChildren(cell, "CheckBox");
            if (obj != null)
            {
                System.Windows.Controls.CheckBox cb = (System.Windows.Controls.CheckBox)obj;
                cb.Focus();
                cb.IsChecked = !cb.IsChecked;
            }
        }
    }

    public DependencyObject FindFirstControlInChildren(DependencyObject obj, string controlType)
    {
        if (obj == null)
            return null;

        // Get a list of all occurrences of a particular type of control (eg "CheckBox") 
        IEnumerable<DependencyObject> ctrls = FindInVisualTreeDown(obj, controlType);
        if (ctrls.Count() == 0)
            return null;

        return ctrls.First();
    }

    public IEnumerable<DependencyObject> FindInVisualTreeDown(DependencyObject obj, string type)
    {
        if (obj != null)
        {
            if (obj.GetType().ToString().EndsWith(type))
            {
                yield return obj;
            }

            for (var i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                foreach (var child in FindInVisualTreeDown(VisualTreeHelper.GetChild(obj, i), type))
                {
                    if (child != null)
                    {
                        yield return child;
                    }
                }
            }
        }
        yield break;
    }
}

এই সব কি করে?

ঠিক আছে, প্রতিবার আমরা আমাদের ডেটাগ্রিডের যে কোনও ঘরে ক্লিক করি, তখন আমরা দেখতে পাই যে ঘরে কোষের মধ্যে একটি চেকবক্স নিয়ন্ত্রণ রয়েছে কিনা। যদি তা হয় , তবে আমরা সেই চেকবক্সে ফোকাস সেট করব এবং এর মান টগল করব

এটি আমার পক্ষে কাজ করে বলে মনে হচ্ছে এবং এটি একটি দুর্দান্ত, সহজেই পুনরায় ব্যবহারযোগ্য সমাধান।

এটা তোলে হতাশ যে আমরা হয় প্রয়োজন এই যদিও করতে লেখ কোডে। ডাব্লুপিএফ এটিকে সারিটি সম্পাদনা মোডে রাখার জন্য ব্যবহার করার সাথে সাথে প্রথম মাউস ক্লিক (একটি ডেটাগ্রিডের চেকবক্সে) "উপেক্ষা করা হয়েছে" ব্যাখ্যাটি বাস্তবসম্মত অ্যাপ্লিকেশনটি যেভাবে কাজ করে তার বিপরীতে।

যদি কোনও ব্যবহারকারী তাদের স্ক্রিনে একটি চেকবক্স দেখতে পান তবে এটি একবার এটি টিক / আনটিক করতে ক্লিক করতে সক্ষম হন। গল্পের শেষে.


1
ধন্যবাদ, আমি "সমাধান" একটি গুচ্ছ চেষ্টা করেছি, কিন্তু এটিই প্রথম যা প্রতিবার সত্যিই কাজ করে বলে মনে হয়। এবং এটি আমার অ্যাপ্লিকেশন আর্কিটেকচারের সাথে সুন্দরভাবে ফিট করে।
গুজে

এই সমাধানটি বাঁধাইয়ের আপডেট করার ক্ষেত্রে ফলাফল দেয়, তবে এখানে একটি: wpf.codeplex.com/wikipage?title=Single- ক্লিক করুন ২০২০ সম্পাদনা করে না।
জাস্টিন সাইমন

2
খুবই জটিল. আমার উত্তর দেখুন। :)
কনস্ট্যান্টিন সালাভাতভ

1
5 বছর পরে এই কোডটি এখনও সামাজিক জীবনের জন্য সময় সাশ্রয় করছে :) কিছু সাধারণ প্রয়োজনীয়তার জন্য, @ কনস্ট্যান্টিনসালাওয়াতভ সমাধান যথেষ্ট। আমার ক্ষেত্রে আমি হ্যান্ডলারের সাথে ডায়নামিক ইভেন্ট অ্যাসোসিয়েশন অর্জনের জন্য মাইকের সমাধানের সাথে আমার কোডটি মিশ্রিত করেছি, আমার গ্রিডে গতিশীল সংখ্যক কলাম রয়েছে, নির্দিষ্ট কক্ষে একটি ক্লিকের সাথে অবশ্যই ডাটাবেসে পরিবর্তনগুলি সংরক্ষণ করতে হবে।
ফের আর

8

এখানে অনেক সহজ সমাধান রয়েছে।

          <DataGridTemplateColumn MinWidth="20" >
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Grid>
                            <CheckBox VerticalAlignment="Center" HorizontalAlignment="Center"/>
                        </Grid>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>

আপনি যদি ব্যবহার DataGridCheckBoxColumn প্রয়োগ করেন তবে প্রথম ক্লিকটি ফোকাস করা, দ্বিতীয় ক্লিকটি চেক করা।

কিন্তু ব্যবহার করছি DataGridTemplateColumn প্রয়োগ করতে জন্য কেবল একটি ক্লিক প্রয়োজন।

দ্বারা DataGridComboboxBoxColumnপ্রয়োগ এবং প্রয়োগের পার্থক্যটিও DataGridTemplateColumnএকই রকম।


আমার জন্য ভাল ব্যাখ্যা এবং তাত্ক্ষণিকভাবে কাজ করেছেন, ধন্যবাদ!
অ্যাস্ট্রালিসসোনিয়াম

8

আমি এটি দিয়ে সমাধান করেছি:

<DataGridTemplateColumn>
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <Viewbox Height="25">
                <CheckBox IsChecked="{Binding TheProperty, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
            </Viewbox>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

একক ক্লিকে সক্রিয় চেকবক্স!


2
ভিউবক্সে আমার চেকবক্সটি মোড়ানো দরকার ছিল না, তবে এই উত্তরটি আমার পক্ষে কাজ করেছে।
JGeerWM

3
এটি আমার কাছে গৃহীত উত্তরের চেয়ে অনেক ক্লিনার সমাধান। ভিউবক্সেরও দরকার নেই। এটি কীভাবে সংজ্ঞায়িত চেকবক্স কলামের চেয়ে আরও ভাল কাজ করে তা মজার।
কেনজারা

6

উপর বেজ জিম Adorno উত্তর এবং তার পোস্টে মন্তব্য, এই সঙ্গে সমাধান MultiTrigger:

<Style TargetType="DataGridCell">
  <Style.Triggers>
    <MultiTrigger>
      <MultiTrigger.Conditions>
    <Condition Property="IsReadOnly" Value="False" />
    <Condition Property="IsMouseOver" Value="True" />
      </MultiTrigger.Conditions>
      <Setter Property="IsEditing" Value="True" />
    </MultiTrigger>
  </Style.Triggers>
</Style>

5

তবুও অন্য একটি সহজ সমাধান হ'ল এই স্টাইলটি আপনার ডেটাগ্রিডকলামে যুক্ত করুন your আপনার স্টাইলের মূল অংশটি খালি থাকতে পারে।

<DataGridCheckBoxColumn>
     <DataGridCheckBoxColumn.ElementStyle>
          <Style TargetType="CheckBox">
           </Style>
     </DataGridCheckBoxColumn.ElementStyle>
</DataGridCheckBoxColumn>

2
চেক / আনচেক করতে স্পেস বারটি টিপলে চেকবক্সটি বাম থেকে মাঝখানে চলে যাবে। শৈলীতে <সেটার সম্পত্তি = "অনুভূমিক অ্যালাইনমেন্ট" মান = "কেন্দ্র" /> যুক্ত করা চেকবক্সকে চলাচল করতে বাধা দেবে।
ইয়ান্টিংচেন

1
<Style x:Key="StilCelula" TargetType="DataGridCell"> 
<Style.Triggers>
 <Trigger Property="IsMouseOver" Value="True">
   <Setter Property="IsEditing" 
     Value="{Binding RelativeSource={x:Static RelativeSource.Self}, 
     Converter={StaticResource CheckBoxColumnToEditingConvertor}}" />
 </Trigger>
</Style.Triggers>
<Style>
Imports System.Globalization
Public Class CheckBoxColumnToEditingConvertor
    Implements IValueConverter
    Public Function Convert(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As CultureInfo) As Object Implements IValueConverter.Convert
        Try

            Return TypeOf TryCast(value, DataGridCell).Column Is DataGridCheckBoxColumn
        Catch ex As Exception
            Return Visibility.Collapsed
        End Try
    End Function

    Public Function ConvertBack(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As CultureInfo) As Object Implements IValueConverter.ConvertBack
        Throw New NotImplementedException()
    End Function
End Class
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.