কনটেক্সটমেনু প্রদর্শনের আগে ডান ক্লিকে ট্রিভিউ নোডটি নির্বাচন করুন


101

কনটেক্সটমেনু প্রদর্শিত হওয়ার ঠিক আগে ডান ক্লিকে ডাব্লুপিএফ ট্রিভিউ নোডটি নির্বাচন করতে চাই।

উইনফোর্ডসের জন্য আমি প্রসঙ্গ মেনুতে ক্লিক করা এই ফাইন্ড নোডের মতো কোড ব্যবহার করতে পারি, ডাব্লুপিএফ বিকল্পগুলি কী?

উত্তর:


131

গাছটি যেভাবে জনবহুল হয়েছিল তার উপর নির্ভর করে প্রেরক এবং ই-উত্সের মানগুলি পৃথক হতে পারে

সম্ভাব্য সমাধানগুলির মধ্যে একটি হ'ল ই.আরিনালসোর্স ব্যবহার করা এবং ভিজ্যুয়ালটিহেল্পার ব্যবহার করে ট্রিভিউআইটেমটি সন্ধান করা:

private void OnPreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
    TreeViewItem treeViewItem = VisualUpwardSearch(e.OriginalSource as DependencyObject);

    if (treeViewItem != null)
    {
        treeViewItem.Focus();
        e.Handled = true;
    }
}

static TreeViewItem VisualUpwardSearch(DependencyObject source)
{
    while (source != null && !(source is TreeViewItem))
        source = VisualTreeHelper.GetParent(source);

    return source as TreeViewItem;
}

এই ইভেন্টটি কি ট্রিভিউ বা ট্রিউভিউ আইটেমের জন্য?
লুই রাইস

4
একটি ডান ক্লিকটি যদি কোনও শূন্য স্থানে থাকে তবে কীভাবে সমস্ত কিছু নির্বাচন করতে হবে?
লুই রাইস

কেবলমাত্র একটি উত্তর যা অন্য 5 জনের মধ্যে সহায়তা করেছিল ... আমি বৃক্ষদর্শন জনসংখ্যার সাথে সত্যিই কিছু ভুল করছি, ধন্যবাদ

4
লুই রাইসের প্রশ্নের উত্তরে: if (treeViewItem == null) treeView.SelectedIndex = -1বা treeView.SelectedItem = null। আমি বিশ্বাস করি হয় কাজ করা উচিত।
জেমস এম

24

আপনি যদি এক্সএএমএল-কেবল সমাধান চান তবে আপনি মিশ্রিত ইন্টারেক্টিভিটি ব্যবহার করতে পারেন।

ধরে TreeViewএকটি থাকার দর্শনযোগ্য মডেলের একটি হায়ারারকিকাল সংগ্রহ করতে বাধ্য তথ্য Booleanসম্পত্তি IsSelectedএবং Stringসম্পত্তি Nameসেইসাথে নামে শিশু আইটেমের একটি সংগ্রহ Children

<TreeView ItemsSource="{Binding Items}">
  <TreeView.ItemContainerStyle>
    <Style TargetType="TreeViewItem">
      <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
    </Style>
  </TreeView.ItemContainerStyle>
  <TreeView.ItemTemplate>
    <HierarchicalDataTemplate ItemsSource="{Binding Children}">
      <TextBlock Text="{Binding Name}">
        <i:Interaction.Triggers>
          <i:EventTrigger EventName="PreviewMouseRightButtonDown">
            <ei:ChangePropertyAction PropertyName="IsSelected" Value="true" TargetObject="{Binding}"/>
          </i:EventTrigger>
        </i:Interaction.Triggers>
      </TextBlock>
    </HierarchicalDataTemplate>
  </TreeView.ItemTemplate>
</TreeView>

দুটি আকর্ষণীয় অংশ রয়েছে:

  1. TreeViewItem.IsSelectedসম্পত্তি আবদ্ধ হয় IsSelectedদেখার মডেলের উপর সম্পত্তি। IsSelectedভিউ-মডেলটিতে সম্পত্তিটিকে সত্যে সেট করা গাছের সাথে সম্পর্কিত নোডটি নির্বাচন করবে।

  2. যখন PreviewMouseRightButtonDownনোড (এই নমুনা একটি চাক্ষুষ পক্ষ থেকে দাবানল TextBlock) IsSelectedদর্শনযোগ্য মডেলের উপর সম্পত্তি সত্যতে সেট করা থাকে। ১ এ ফিরে যান আপনি দেখতে পাচ্ছেন যে গাছে ক্লিক করা সংশ্লিষ্ট নোডটি নির্বাচিত নোড হয়ে যায়।

ওয়ান ওয়ে আপনার প্রকল্পের মিশান ইন্ট্যার্যাক্টিভিটির পেতে NuGet প্যাকেজ ব্যবহার করা Unofficial.Blend.Interactivity


4
দুর্দান্ত উত্তর, আপনাকে ধন্যবাদ! নাম iএবং স্থানের eiম্যাপিংগুলি কীসের সাথে সংবিধানগুলি পাওয়া যায় সেগুলি সমাধান করে তা দেখাতে সহায়ক হবে I আমি অনুমান করি: xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"এবং xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions", যা যথাক্রমে System.Windows.Interactivity এবং Microsoft.Expression.Inteferences সমাবেশগুলিতে পাওয়া যায়।
prlc

এটি কোনও কার্যকর হয়নি কারণ বাউন্ড ডেটা অবজেক্টের ChangePropertyActionএকটি IsSelectedসম্পত্তি সেট করার চেষ্টা করছে যা ইউআইয়ের অংশ নয়, সুতরাং এর IsSelectedসম্পত্তি নেই। আমি কি ভুল কিছু করছি?
আন্তোনন প্রোচাজকা

@ অ্যান্টনপ্রোচকা: আমার উত্তরটির প্রয়োজন যে আপনার "ডেটা অবজেক্ট" (বা মডেল দেখুন) IsSelectedআমার উত্তরের দ্বিতীয় অনুচ্ছেদে বর্ণিত একটি সম্পত্তি আছে : ধরে নিন যে বুলিয়ান সম্পত্তি সম্বলিতTreeView ভিউ-মডেলগুলির একটি শ্রেণিবদ্ধ সংগ্রহের সাথে আবদ্ধ ডেটা ...IsSelected (আমার জোর)
মার্টিন লিভারেজ

16

"আইটেম.ফোকাস ();" "আইটেম.আইএসএলেজড = ট্রু" ব্যবহার করে 100% কাজ করবে বলে মনে হচ্ছে না; করে


এই টিপ জন্য ধন্যবাদ। আমাকে সাহায্য করে ছিল.
i8abug

ভালো পরামর্শ. আমি প্রথমে ফোকাস () কে কল করব এবং তারপরে ইসসলেক্টড = সত্য সেট করলাম।
জিম গমেস

12

এক্সএএমএল-এ, এক্সএএমএল-এ একটি পূর্বরূপমাউস রাইটবাটনডাউন হ্যান্ডলার যুক্ত করুন:

    <TreeView.ItemContainerStyle>
        <Style TargetType="{x:Type TreeViewItem}">
            <!-- We have to select the item which is right-clicked on -->
            <EventSetter Event="TreeViewItem.PreviewMouseRightButtonDown" Handler="TreeViewItem_PreviewMouseRightButtonDown"/>
        </Style>
    </TreeView.ItemContainerStyle>

তারপরে ইভেন্টটি হ্যান্ডেল করুন:

    private void TreeViewItem_PreviewMouseRightButtonDown( object sender, MouseEventArgs e )
    {
        TreeViewItem item = sender as TreeViewItem;
        if ( item != null )
        {
            item.Focus( );
            e.Handled = true;
        }
    }

4
এটি প্রত্যাশার মতো কাজ করে না, আমি সর্বদা একজন প্রেরক হিসাবে মূল উপাদানটি পাই। আমি একটি অনুরূপ সমাধান পেয়েছি একটি এক সামাজিক.msdn.microsoft.com/forums/en-US/wpf/thread/… ইভেন্ট হ্যান্ডলাররা প্রত্যাশা অনুযায়ী এইভাবে কাজ করে। আপনার কোডটি গ্রহণ করার জন্য কোনও পরিবর্তন? :-)
alex2k8

এটি আপাতত নির্ভর করে আপনি কীভাবে গাছের দৃশ্য উপস্থাপন করেন তার উপর। আমার পোস্ট করা কোডটি কাজ করে, কারণ এটি আমার সরঞ্জামগুলির একটিতে আমি সঠিক কোড ব্যবহার করি।
স্টিফান

দ্রষ্টব্য আপনি যদি এখানে কোনও ডিবাগ পয়েন্ট সেট করেন তবে আপনি দেখতে পাচ্ছেন যে আপনার প্রেরক কী প্রকার যা অবশ্যই আপনি গাছটি কীভাবে সেটআপ করবেন তার উপর ভিত্তি করে

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

12

অ্যালেক্স 2 কে 8 থেকে আসল ধারণাটি ব্যবহার করে সঠিকভাবে উইজার সফটওয়্যার লিমিটেডের অ-ভিজ্যুয়ালগুলি সঠিকভাবে পরিচালনা করা, স্টেফানের এক্সএএমএল, এরেল্যান্ডের ইসসলেক্টড এবং সত্যিকার অর্থে স্থিতিশীল পদ্ধতি জেনারিক করার ক্ষেত্রে আমার অবদান:

এক্সএএমএল:

<TreeView.ItemContainerStyle> 
    <Style TargetType="{x:Type TreeViewItem}"> 
        <!-- We have to select the item which is right-clicked on --> 
        <EventSetter Event="TreeViewItem.PreviewMouseRightButtonDown"
                     Handler="TreeViewItem_PreviewMouseRightButtonDown"/> 
    </Style> 
</TreeView.ItemContainerStyle>

সি # কোড পিছনে:

void TreeViewItem_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
    TreeViewItem treeViewItem = 
              VisualUpwardSearch<TreeViewItem>(e.OriginalSource as DependencyObject);

    if(treeViewItem != null)
    {
        treeViewItem.IsSelected = true;
        e.Handled = true;
    }
}

static T VisualUpwardSearch<T>(DependencyObject source) where T : DependencyObject
{
    DependencyObject returnVal = source;

    while(returnVal != null && !(returnVal is T))
    {
        DependencyObject tempReturnVal = null;
        if(returnVal is Visual || returnVal is Visual3D)
        {
            tempReturnVal = VisualTreeHelper.GetParent(returnVal);
        }
        if(tempReturnVal == null)
        {
            returnVal = LogicalTreeHelper.GetParent(returnVal);
        }
        else returnVal = tempReturnVal;
    }

    return returnVal as T;
}

সম্পাদনা: পূর্ববর্তী কোডটি এই দৃশ্যের জন্য সর্বদা সূক্ষ্মভাবে কাজ করেছিল, তবে অন্য দৃশ্যে ভিজুয়ালটি ট্রিহেল্পার.গেটপ্যারেন্ট নালাগুলি প্রত্যাবর্তন করেছে যখন লজিক্যাল ট্রিহেল্পার একটি মান ফিরিয়ে দেয়, তাই এটি স্থির করে দেওয়া হয়েছিল।


4
এটিকে আরও জানাতে
টেরেন্স

7

প্রায় ডানদিকে , তবে আপনার গাছের অ-ভিজ্যুয়ালগুলি লক্ষ্য করা দরকার ( Runউদাহরণস্বরূপ, যেমন)।

static DependencyObject VisualUpwardSearch<T>(DependencyObject source) 
{
    while (source != null && source.GetType() != typeof(T))
    {
        if (source is Visual || source is Visual3D)
        {
            source = VisualTreeHelper.GetParent(source);
        }
        else
        {
            source = LogicalTreeHelper.GetParent(source);
        }
    }
    return source; 
}

এই জেনেরিক পদ্ধতিটি কিছুটা অদ্ভুত বলে মনে হয় যখন আমি ট্রিভিউআইটিম ট্রিভিউআইটেম = ভিজ্যুয়ালআপওয়ার্ডস << ট্রিভিউআইটেম> লিখি তখন এটি কীভাবে ব্যবহার করতে পারি; এটি আমাকে রূপান্তর ত্রুটি দেয়
রতি_জি

ট্রিভিউআইটেম ট্রি ট্রিউইউআইটিম = ভিজ্যুয়ালওয়ার্ডসার্চ <ট্রি ট্রিউইউ আইটেম> (যেমন ডিপেন্ডেন্সিঅবজেক্ট হিসাবে অরিজিনালসোর্স) ট্রিভিউআইটেম হিসাবে;
অ্যান্টনি উইজার

7

আমি মনে করি একটি ক্লাস হ্যান্ডলারের নিবন্ধকরণের কৌশলটি করা উচিত। আপনার app.xaml.cs কোড ফাইলে ট্রিভিউআইটেমের পূর্বরূপমাউসরাইটবাটনডাউন এভেন্টে কেবল একটি রাউটেড ইভেন্ট হ্যান্ডলারটি নিবন্ধ করুন:

/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        EventManager.RegisterClassHandler(typeof(TreeViewItem), TreeViewItem.PreviewMouseRightButtonDownEvent, new RoutedEventHandler(TreeViewItem_PreviewMouseRightButtonDownEvent));

        base.OnStartup(e);
    }

    private void TreeViewItem_PreviewMouseRightButtonDownEvent(object sender, RoutedEventArgs e)
    {
        (sender as TreeViewItem).IsSelected = true;
    }
}

আমার জন্য কাজ! এবং সহজ।
dvallejo

4
হ্যালো নাথান দেখে মনে হচ্ছে কোডটি বিশ্বব্যাপী এবং প্রতিটি ট্রিভিউয়কে প্রভাবিত করবে। স্থানীয়ভাবে সমাধান পাওয়া কি ভাল হবে না? এটি পার্শ্ব প্রতিক্রিয়া তৈরি করতে পারে?
এরিক ওয়েললেট

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

2

এমভিভিএম ব্যবহার করে এটি সমাধানের আরেকটি উপায় হ'ল আপনার ভিউ মডেলের ডান ক্লিকের জন্য বাইন্ড কমান্ড। সেখানে আপনি অন্যান্য যুক্তিও নির্দিষ্ট করতে পারেন source.IsSelected = true। এটি কেবল xmlns:i="http://schemas.microsoft.com/expression/2010/intera‌​ctivity"থেকে ব্যবহার করে System.Windows.Interactivity

এক্সএএমএল দেখার জন্য:

<TreeView ItemsSource="{Binding Items}">
  <TreeView.ItemContainerStyle>
    <Style TargetType="TreeViewItem">
      <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
    </Style>
  </TreeView.ItemContainerStyle>
  <TreeView.ItemTemplate>
    <HierarchicalDataTemplate ItemsSource="{Binding Children}">
      <TextBlock Text="{Binding Name}">
        <i:Interaction.Triggers>
          <i:EventTrigger EventName="PreviewMouseRightButtonDown">
            <i:InvokeCommandAction Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.TreeViewItemRigthClickCommand}" CommandParameter="{Binding}" />
          </i:EventTrigger>
        </i:Interaction.Triggers>
      </TextBlock>
    </HierarchicalDataTemplate>
  </TreeView.ItemTemplate>
</TreeView>

মডেল দেখুন:

    public ICommand TreeViewItemRigthClickCommand
    {
        get
        {
            if (_treeViewItemRigthClickCommand == null)
            {
                _treeViewItemRigthClickCommand = new RelayCommand<object>(TreeViewItemRigthClick);
            }
            return _treeViewItemRigthClickCommand;
        }
    }
    private RelayCommand<object> _treeViewItemRigthClickCommand;

    private void TreeViewItemRigthClick(object sourceItem)
    {
        if (sourceItem is Item)
        {
            (sourceItem as Item).IsSelected = true;
        }
    }

1

HierarchicalDataTemplate পদ্ধতিতে বাচ্চাদের বাছাই করতে আমার সমস্যা হয়েছিল। যদি আমি কোনও নোডের শিশু নির্বাচন করি তবে এটি কোনওভাবে সেই সন্তানের মূল পিতামাতার নির্বাচন করবে। আমি জানতে পেরেছি যে মাউস রাইটবাটনডাউন ইভেন্টটি শিশুটির প্রতিটি স্তরের জন্য ডাকবে। উদাহরণস্বরূপ, আপনার যদি গাছের মতো কিছু থাকে:

আইটেম 1
   - শিশু 1
   - শিশু 2
      - Subitem1
      - Subitem2

যদি আমি সাবাইটেম 2 নির্বাচন করি তবে ইভেন্টটি তিনবার আগুন ধরিয়ে দেবে এবং আইটেম 1 নির্বাচন করা হবে। আমি এটি বুলিয়ান এবং একটি অ্যাসিনক্রোনাস কল দিয়ে সমাধান করেছি।

private bool isFirstTime = false;
    protected void TaskTreeView_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
    {
        var item = sender as TreeViewItem;
        if (item != null && isFirstTime == false)
        {
            item.Focus();
            isFirstTime = true;
            ResetRightClickAsync();
        }
    }

    private async void ResetRightClickAsync()
    {
        isFirstTime = await SetFirstTimeToFalse();
    }

    private async Task<bool> SetFirstTimeToFalse()
    {
        return await Task.Factory.StartNew(() => { Thread.Sleep(3000); return false; });
    }

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


উত্তর সেট করা MouseButtonEventArgs.Handledহয় true। যেহেতু শিশুটিকে প্রথম বলা হয়। এই সম্পত্তিটিকে সত্যে সেটিংস করা পিতামাতার কাছে অন্য কলগুলি অক্ষম করে।
বাসিত আনোয়ার

0

আপনি এটি মাউস ডাউন ইভেন্টের সাহায্যে নির্বাচন করতে পারেন। কনটেক্সট মেনুতে কিক করার আগে এটি নির্বাচনকে ট্রিগার করবে।


0

আপনি যদি এমভিভিএম প্যাটার্নের মধ্যে থাকতে চান তবে আপনি নিম্নলিখিতটি করতে পারেন:

দেখুন:

<TreeView x:Name="trvName" ItemsSource="{Binding RootElementListView}" Tag="{Binding ClickedTreeElement, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate DataType="{x:Type models:YourTreeElementClass}" ItemsSource="{Binding Path=Subreports}">
            <TextBlock Text="{Binding YourTreeElementDisplayProperty}" PreviewMouseRightButtonDown="TreeView_PreviewMouseRightButtonDown"/>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

পিছনে কোড:

private void TreeView_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
    if (sender is TextBlock tb && tb.DataContext is YourTreeElementClass te)
    {
        trvName.Tag = te;
    }
}

ভিউমোডেল:

private YourTreeElementClass _clickedTreeElement;

public YourTreeElementClass ClickedTreeElement
{
    get => _clickedTreeElement;
    set => SetProperty(ref _clickedTreeElement, value);
}

এখন আপনি হয় ক্লিকডট্রিএলমেন্ট সম্পত্তি পরিবর্তনের বিষয়ে প্রতিক্রিয়া জানাতে পারেন বা আপনি একটি আদেশ ব্যবহার করতে পারেন যা অভ্যন্তরীণভাবে ক্লিকডট্রিএলমেন্টের সাথে কাজ করে।

বর্ধিত দর্শন:

<UserControl ...
             xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity">
    <TreeView x:Name="trvName" ItemsSource="{Binding RootElementListView}" Tag="{Binding ClickedTreeElement, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="MouseRightButtonUp">
                <i:InvokeCommandAction Command="{Binding HandleRightClickCommand}"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>
        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate DataType="{x:Type models:YourTreeElementClass}" ItemsSource="{Binding Path=Subreports}">
                <TextBlock Text="{Binding YourTreeElementDisplayProperty}" PreviewMouseRightButtonDown="TreeView_PreviewMouseRightButtonDown"/>
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
    </TreeView>
</UserControl>
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.