ডাব্লুপিএফ ট্রিভিউতে ডেটা বদ্ধ নির্বাচন করা হয়েছে tem


240

ডাব্লুপিএফ-ট্রিভিউতে নির্বাচিত আইটেমটি কীভাবে পুনরুদ্ধার করব? আমি এক্সএএমএল-তে এটি করতে চাই, কারণ আমি এটি আবদ্ধ করতে চাই।

আপনি মনে করতে পারেন যে এটি SelectedItemকিন্তু দৃশ্যত যা বিদ্যমান নেই কেবল পঠনযোগ্য এবং তাই অকেজো।

এটি আমি করতে চাই:

<TreeView ItemsSource="{Binding Path=Model.Clusters}" 
            ItemTemplate="{StaticResource ClusterTemplate}"
            SelectedItem="{Binding Path=Model.SelectedCluster}" />

আমি SelectedItemআমার মডেলের একটি সম্পত্তিতে বাঁধতে চাই ।

তবে এটি আমাকে ত্রুটি দেয়:

'সিলেক্ট আইটেম' সম্পত্তি কেবল পঠনযোগ্য এবং মার্কআপ থেকে সেট করা যায় না।

সম্পাদনা করুন: ঠিক আছে, আমি এটি সমাধান করেছি এইভাবে:

<TreeView
          ItemsSource="{Binding Path=Model.Clusters}" 
          ItemTemplate="{StaticResource HoofdCLusterTemplate}"
          SelectedItemChanged="TreeView_OnSelectedItemChanged" />

এবং আমার এক্সএএমএল এর কোডবাইন্ডফাইলে:

private void TreeView_OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
    Model.SelectedCluster = (Cluster)e.NewValue;
}

50
মানুষ এই স্তন্যপান। এটা শুধু আমাকে আঘাত। আমি এখানে একটি শালীন উপায় আছে তা খুঁজে পেতে এখানে এসেছি এবং আমি কেবল বোকা। এই প্রথম আমি দুঃখ পেয়েছি যে আমি বোকা নই ..
আন্দ্রে রিনিয়া

6
এটি সত্যিই বাধ্যতামূলক ধারণাটিকে ডুবিয়ে দেয় এবং গণ্ডগোল করে দেয়
ডেল্টা

আশা করি এটি আইকামন্ডে পরিবর্তিত কল ফিরে নির্বাচিত একটি ট্রি ভিউ আইটেমের সাথে আবদ্ধ হতে কাউকে সহায়তা করতে পারে জ্যাকোবালোয়েসিয়াস.ওয়ার্ডপ্রেস.কম ২০১২
জ্যাকব অলসিয়াস

9
বাইন্ডিং এবং এমভিভিএমের ক্ষেত্রে, পিছনের কোডটি "নিষিদ্ধ" হয় না, বরং পিছনের কোডটিতে ভিউ সমর্থন করা উচিত। অন্য যে সমস্ত সমাধান আমি দেখেছি তার থেকে আমার মতে, পিছনের কোডটি একটি আরও ভাল বিকল্প, যেহেতু এটি এখনও ভিউমোডেলের সাথে "বাঁধাই করা" দেখায়। একমাত্র নেতিবাচক হ'ল যদি আপনার কেবলমাত্র এক্সএএমএল-তে কাজ করে এমন কোনও ডিজাইনারের সাথে একটি দল থাকে, তবে পিছনের কোডটি ভাঙা / উপেক্ষিত হতে পারে। এটি প্রয়োগের জন্য 10 সেকেন্ড সময় লাগে এমন কোনও সমাধানের জন্য অর্থ প্রদানের জন্য একটি অল্প মূল্য।
nrjohnstone

সম্ভবত সবচেয়ে সহজ পদ্ধিতি হল সমাধান একটি: stackoverflow.com/questions/1238304/...
JoanComasFdz

উত্তর:


240

আমি বুঝতে পারি এটি ইতিমধ্যে একটি উত্তর গৃহীত হয়েছে, কিন্তু আমি সমস্যার সমাধানের জন্য এটি একসাথে রেখেছি। এটি ডেল্টা সমাধানের অনুরূপ ধারণা ব্যবহার করে তবে ট্রিভিউউয়ের সাবক্লাস করার প্রয়োজন ছাড়াই:

public class BindableSelectedItemBehavior : Behavior<TreeView>
{
    #region SelectedItem Property

    public object SelectedItem
    {
        get { return (object)GetValue(SelectedItemProperty); }
        set { SetValue(SelectedItemProperty, value); }
    }

    public static readonly DependencyProperty SelectedItemProperty =
        DependencyProperty.Register("SelectedItem", typeof(object), typeof(BindableSelectedItemBehavior), new UIPropertyMetadata(null, OnSelectedItemChanged));

    private static void OnSelectedItemChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        var item = e.NewValue as TreeViewItem;
        if (item != null)
        {
            item.SetValue(TreeViewItem.IsSelectedProperty, true);
        }
    }

    #endregion

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

        this.AssociatedObject.SelectedItemChanged += OnTreeViewSelectedItemChanged;
    }

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

        if (this.AssociatedObject != null)
        {
            this.AssociatedObject.SelectedItemChanged -= OnTreeViewSelectedItemChanged;
        }
    }

    private void OnTreeViewSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
    {
        this.SelectedItem = e.NewValue;
    }
}

তারপরে আপনি এটি আপনার এক্সএএমএল হিসাবে এটি ব্যবহার করতে পারেন:

<TreeView>
    <e:Interaction.Behaviors>
        <behaviours:BindableSelectedItemBehavior SelectedItem="{Binding SelectedItem, Mode=TwoWay}" />
    </e:Interaction.Behaviors>
</TreeView>

আশা করি এটি কারও সাহায্য করবে!


5
ব্রেন্টের নির্দেশ অনুসারে আমাকে বাধ্যতামূলকভাবে মোড = টু ওয়েয়ে যুক্ত করা দরকার। আমি "ব্লেন্ডার" নই তাই সিস্টেমের কাছ থেকে আচরণ <> শ্রেণীর সাথে পরিচিত ছিলাম না। সমাবেশটি এক্সপ্রেশন মিশ্রণের অংশ। যারা এই সমাবেশ পেতে ট্রায়াল কিনতে / ইনস্টল করতে চান না তাদের জন্য আপনি ব্লেন্ডএসডিকে ডাউনলোড করতে পারেন যার মধ্যে রয়েছে System.Windows.Interactivity। ৩.৫ এর জন্য ব্লেন্ডএসডিকে ... আমার মনে হয় এটি 4.0 এর জন্য ব্লেন্ডএসডি 4। দ্রষ্টব্য: এটি কেবল আপনাকে কোন আইটেমটি নির্বাচিত তা পেতে অনুমতি দেয়, আপনাকে নির্বাচিত আইটেমটি সেট করতে দেয় না
মাইক রাওলি

4
আপনি ফ্রেমওয়ার্কপ্রোপার্টিমেটাটাটা (নাল, ফ্রেমওয়ার্কপ্র্টির্মিটাডাটাঅ্যাপশনস.বিন্ডসটওওয়াইবাইডিফল্ট, অনসিলিটেডআইটেম চেঞ্জড) দ্বারা ইউআইপিপ্রপার্টিমেটাটাটাও প্রতিস্থাপন করতে পারেন);
ফিলিমিন্ডজি

3
এই সমস্যা সমাধানের জন্য একটি পন্থা হবে stackoverflow.com/a/18700099/4227
bitbonk

2
@ লুকাস ঠিক উপরের এক্সএএমএল কোড স্নিপেটে দেখানো হয়েছে। শুধু প্রতিস্থাপন {Binding SelectedItem, Mode=TwoWay}সঙ্গে{Binding MyViewModelField, Mode=TwoWay}
স্টিভ Greatrex

4
@ পাসল এটিxmlns:e="http://schemas.microsoft.com/expression/2010/interactivity"
স্টিভ গ্রেট্রেক্স

46

এই সম্পত্তি বিদ্যমান: ট্রিভিউ.সিলেক্টড আইটেম

তবে এটি কেবল পঠনযোগ্য, তাই আপনি এটি একটি বাঁধার মাধ্যমে নির্ধারণ করতে পারবেন না, কেবল এটি পুনরুদ্ধার করুন


আমি এই উত্তর গ্রহণ, কারণ সেখানে আমি এই লিঙ্ক, যা আমার নিজের উত্তর যাক পাওয়া যায়নি: msdn.microsoft.com/en-us/library/ms788714.aspx
Natrium

1
TreeView.SelectedItemব্যবহারকারী যখন কোনও আইটেম (ওরফে OneWayToSource) নির্বাচন করেন তখন আমি কি মডেলটির কোনও সম্পত্তিকে প্রভাবিত করতে পারি ?
শিমি ওয়েটজ্যান্ডলার

43

সংযুক্ত বৈশিষ্ট্য এবং কোনও বাহ্যিক নির্ভরতা সহ উত্তর দিন, প্রয়োজনটি কখনই উত্থিত হওয়া উচিত!

আপনি একটি সংযুক্ত সম্পত্তি তৈরি করতে পারেন যা বাইন্ডেবল এবং এতে একটি গেটর এবং সেটার রয়েছে:

public class TreeViewHelper
{
    private static Dictionary<DependencyObject, TreeViewSelectedItemBehavior> behaviors = new Dictionary<DependencyObject, TreeViewSelectedItemBehavior>();

    public static object GetSelectedItem(DependencyObject obj)
    {
        return (object)obj.GetValue(SelectedItemProperty);
    }

    public static void SetSelectedItem(DependencyObject obj, object value)
    {
        obj.SetValue(SelectedItemProperty, value);
    }

    // Using a DependencyProperty as the backing store for SelectedItem.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty SelectedItemProperty =
        DependencyProperty.RegisterAttached("SelectedItem", typeof(object), typeof(TreeViewHelper), new UIPropertyMetadata(null, SelectedItemChanged));

    private static void SelectedItemChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        if (!(obj is TreeView))
            return;

        if (!behaviors.ContainsKey(obj))
            behaviors.Add(obj, new TreeViewSelectedItemBehavior(obj as TreeView));

        TreeViewSelectedItemBehavior view = behaviors[obj];
        view.ChangeSelectedItem(e.NewValue);
    }

    private class TreeViewSelectedItemBehavior
    {
        TreeView view;
        public TreeViewSelectedItemBehavior(TreeView view)
        {
            this.view = view;
            view.SelectedItemChanged += (sender, e) => SetSelectedItem(view, e.NewValue);
        }

        internal void ChangeSelectedItem(object p)
        {
            TreeViewItem item = (TreeViewItem)view.ItemContainerGenerator.ContainerFromItem(p);
            item.IsSelected = true;
        }
    }
}

আপনার এক্সএএমএলতে সেই শ্রেণিটি সহ নেমস্পেসের ঘোষণাটি যুক্ত করুন এবং নীচে বাঁধুন (স্থানীয় নামটি কীভাবে নামকরণের ঘোষণার নাম দিয়েছি):

        <TreeView ItemsSource="{Binding Path=Root.Children}" local:TreeViewHelper.SelectedItem="{Binding Path=SelectedItem, Mode=TwoWay}">

    </TreeView>

এখন আপনি নির্বাচিত আইটেমটি বেঁধে রাখতে পারেন, এবং প্রোগ্রামের পরিবর্তে এটি আপনার ভিউ মডেলে সেট করতে পারেন, যদি সেই প্রয়োজনীয়তাটি কখনও না ঘটে। এটি অবশ্যই ধরে নেওয়া হচ্ছে যে আপনি সেই নির্দিষ্ট সম্পত্তিতে আইএনটিফায়ারপ্রোট্টি চেঞ্জড প্রয়োগ করেছেন।


4
+1, এই থ্রেডের সেরা উত্তর ইমো। System.Windows.Interactivity এর উপর কোনও নির্ভরতা নেই এবং দ্বি-মুখী বাঁধাইয়ের অনুমতি দেয় (একটি এমভিভিএম পরিবেশে প্রোগ্রাম্যাটিকভাবে সেট করা)। পারফেক্ট।
ক্রিস রে

5
এই পদ্ধতির সাথে সমস্যা হ'ল বাছাই করা আইটেমটি একবারে বাইন্ডিংয়ের মাধ্যমে সেট হয়ে গেলে (যেমন ভিউমোডেল থেকে) একবার ব্যবহার করা শুরু করা হবে। যদি ভিএম এর প্রাথমিক মানটি শূন্য হয়, তবে বাইন্ডিংটি ডিপি মান আপডেট করবে না, এবং আচরণটি সক্রিয় হবে না। আপনি আলাদা ডিফল্ট নির্বাচিত আইটেম (যেমন একটি অবৈধ আইটেম) ব্যবহার করে এটি ঠিক করতে পারেন।
চিহ্নিত করুন

6
@ মার্ক: সংযুক্ত সম্পত্তিটির ইউআইপ্রোপার্টিমেটাডেটা ইনস্ট্যান্ট করার সময় উপরের শূন্যটির পরিবর্তে কেবলমাত্র নতুন অবজেক্ট () ব্যবহার করুন। সমস্যাটি তখনই চলে যাওয়া উচিত ...
বার্নেলবয়

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

1
ট্রিভিউআইটিমে কাস্ট করার ক্ষেত্রেও আমার সমস্যা হচ্ছে। এই মুহুর্তে, আইটেমকন্টেইনারজেইনারটিতে কেবলমাত্র মূল আইটেমের উল্লেখ পাওয়া যায়, তবে আমার এটিও প্রয়োজন যে মূলগুলি নন-রুট আইটেমগুলি পেতে সক্ষম হয়। আপনি যদি কোনওটির কাছে একটি রেফারেন্স পাস করেন তবে কাস্ট ব্যর্থ হয় এবং শূন্য ফিরে আসে। কীভাবে এটি ঠিক করা যেতে পারে তা নিশ্চিত নন?
বব টাওয়ে

39

ঠিক আছে, আমি একটি সমাধান খুঁজে পেয়েছি। এটি গণ্ডগোল সরিয়ে দেয়, যাতে এমভিভিএম কাজ করে।

প্রথমে এই শ্রেণিটি যুক্ত করুন:

public class ExtendedTreeView : TreeView
{
    public ExtendedTreeView()
        : base()
    {
        this.SelectedItemChanged += new RoutedPropertyChangedEventHandler<object>(___ICH);
    }

    void ___ICH(object sender, RoutedPropertyChangedEventArgs<object> e)
    {
        if (SelectedItem != null)
        {
            SetValue(SelectedItem_Property, SelectedItem);
        }
    }

    public object SelectedItem_
    {
        get { return (object)GetValue(SelectedItem_Property); }
        set { SetValue(SelectedItem_Property, value); }
    }
    public static readonly DependencyProperty SelectedItem_Property = DependencyProperty.Register("SelectedItem_", typeof(object), typeof(ExtendedTreeView), new UIPropertyMetadata(null));
}

এবং এটি আপনার xaml এ যুক্ত করুন:

 <local:ExtendedTreeView ItemsSource="{Binding Items}" SelectedItem_="{Binding Item, Mode=TwoWay}">
 .....
 </local:ExtendedTreeView>

3
এটি এখন পর্যন্ত আমার পক্ষে কাজ করার কাছাকাছি এসে গেছে। আমি এই সমাধানটি সত্যিই পছন্দ করি।
রাচেল

1
কেন জানি না তবে এটি আমার পক্ষে কার্যকর হয় নি :( আমি গাছ থেকে বাছাই করা আইটেমটি গাছ থেকে পেয়েছিলাম তবে তদ্বিপরীতভাবে নয় - নির্বাচিত আইটেমটিকে গাছের বাইরে থেকে পরিবর্তন করতে
পেরেছিলাম

বাইন্ডসটওওয়াইবিডিফল্ট হিসাবে নির্ভরতা সম্পত্তি সেট করা কিছুটা স্বচ্ছন্দ হবে তবে আপনাকে এক্সএএমএলে টুওয়ে নির্দিষ্ট করার দরকার নেই
স্টিফেন হল্ট

এটি সর্বোত্তম পন্থা। এটি ইন্টারঅ্যাক্টিভিটি রেফারেন্স ব্যবহার করে না, এটি পিছনে কোড ব্যবহার করে না, এতে কিছু আচরণের মতো মেমরি ফাঁস হয় না। ধন্যবাদ.
আলেকজান্দ্রু ডিকু

উল্লিখিত হিসাবে, এই সমাধানটি 2 ওয়ে বাইন্ডিংয়ের সাথে কাজ করে না। আপনি যদি ভিউ মডেলে মান সেট করেন, পরিবর্তনটি ট্রিভিউতে প্রচার করে না।
রিচার্ড মুর

25

এটি ওপি প্রত্যাশার চেয়ে কিছুটা বেশি উত্তর দেয় ... তবে আমি আশা করি এটি কমপক্ষে কাউকে সহায়তা করতে পারে।

আপনি যদি একটি চালানো চান ICommandযখনই SelectedItemপরিবর্তিত, আপনি একটি ইভেন্ট এবং একটি সম্পত্তি ব্যবহারের উপর কমান্ড আবদ্ধ করতে পারেন SelectedItemমধ্যে ViewModelআর প্রয়োজন হয় না।

তাই না:

1- রেফারেন্স যুক্ত করুন System.Windows.Interactivity

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

2- ইভেন্টটি কমান্ড বাঁধুন SelectedItemChanged

<TreeView x:Name="myTreeView" Margin="1"
            ItemsSource="{Binding Directories}">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="SelectedItemChanged">
            <i:InvokeCommandAction Command="{Binding SomeCommand}"
                                   CommandParameter="
                                            {Binding ElementName=myTreeView
                                             ,Path=SelectedItem}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <TreeView.ItemTemplate>
           <!-- ... -->
    </TreeView.ItemTemplate>
</TreeView>

3
রেফারেন্স System.Windows.Interactivity: NuGet থেকে ইনস্টল করা যাবে nuget.org/packages/System.Windows.Interactivity.WPF
Junle লি

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

1
মাইক্রোসফ্ট দ্বারা 2018 এর শেষের দিকে ডাব্লুপিএফ এর জন্য এক্সএএমএল বিহিভিয়ার্স চালু হয়েছিল It এর পরিবর্তে এটি ব্যবহার করা যেতে পারে System.Windows.Interactivity। এটি আমার জন্য কাজ করা হয়েছিল (। নেট কোর প্রকল্পের সাথে চেষ্টা করে)। জিনিসগুলি সেট আপ করার জন্য, কেবল মাইক্রোসফ্ট. এক্সএলএল.বিহ্যাভির্স.ডাব্লুপিএফ নুগেট প্যাকেজ যুক্ত করুন, নাম স্থানটি এতে পরিবর্তন করুন xmlns:i="http://schemas.microsoft.com/xaml/behaviors"। আরও তথ্য পেতে - দয়া করে ব্লগটি দেখুন
rychlmoj

19

এটি কেবলমাত্র বাইন্ডিং এবং গ্যালসফট এমভিভিএম লাইট লাইব্রেরির ইভেন্টটোকমন্ড ব্যবহার করে 'নিখর' উপায়ে সম্পন্ন করা যায়। আপনার ভিএম-তে একটি কমান্ড যুক্ত করুন যা নির্বাচিত আইটেমটি পরিবর্তিত হলে ডাকা হবে এবং প্রয়োজনীয় ক্রিয়াকলাপ সম্পাদন করতে আদেশটি শুরু করুন ize এই উদাহরণে আমি রিলে কম্যান্ড ব্যবহার করেছি এবং কেবলমাত্র নির্বাচিত ক্লাস্টার সম্পত্তি সেট করব।

public class ViewModel
{
    public ViewModel()
    {
        SelectedClusterChanged = new RelayCommand<Cluster>( c => SelectedCluster = c );
    }

    public RelayCommand<Cluster> SelectedClusterChanged { get; private set; } 

    public Cluster SelectedCluster { get; private set; }
}

তারপরে আপনার এক্সএএমএলে ইভেন্টটিকোমন্ড আচরণ যুক্ত করুন। এটি মিশ্রণটি ব্যবহার করা সত্যিই সহজ।

<TreeView
      x:Name="lstClusters"
      ItemsSource="{Binding Path=Model.Clusters}" 
      ItemTemplate="{StaticResource HoofdCLusterTemplate}">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="SelectedItemChanged">
            <GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding SelectedClusterChanged}" CommandParameter="{Binding ElementName=lstClusters,Path=SelectedValue}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</TreeView>

এটি একটি দুর্দান্ত সমাধান বিশেষত যদি আপনি ইতিমধ্যে এমভিভিএমলাইট টুলকিট ব্যবহার করছেন। তবে এটি নির্বাচিত নোড সেট করার সমস্যাটি সমাধান করে না এবং ট্রিভিউউলে নির্বাচনটি আপডেট করে।
কেফট

12

সব জটিল ... ক্যালিবার্ন মাইক্রো (http://caliburnmicro.codeplex.com/) এর সাথে যান

দেখুন:

<TreeView Micro:Message.Attach="[Event SelectedItemChanged] = [Action SetSelectedItem($this.SelectedItem)]" />

ViewModel:

public void SetSelectedItem(YourNodeViewModel item) {}; 

5
হ্যাঁ ... এবং ট্রিভিউ- তে সেলেক্ট আইটেম সেট করার অংশটি কোথায় ?
এমএনএন

ক্যালিবার্ন চমৎকার এবং মার্জিত। নেস্টেড হায়ারারিচিগুলির জন্য বেশ সহজেই কাজ করে
পুরুষসার্থ

8

আমি এই পৃষ্ঠাটি জুড়ে এসেছি মূল লেখকের মতো একই উত্তর খুঁজছি, এবং প্রমাণ করার জন্য এটি করার একাধিক উপায় রয়েছে, আমার পক্ষে সমাধানটি এতদূর এখানে দেওয়া উত্তরগুলির চেয়ে আরও সহজ ছিল, তাই আমি বুঝতে পেরেছিলাম আমিও যুক্ত করতে পারি গাদা যাও।

বাইন্ডিংয়ের অনুপ্রেরণা হ'ল এটি ভাল & এমভিভিএম রাখা। ভিউমোডেলের সম্ভাব্য ব্যবহারটি সম্পত্তি হিসাবে ডাব্লু / নাম যেমন "কারেন্টইটিঙ্গি" থাকতে পারে এবং অন্য কোথাও, ডেটা কনটেক্সট অন্য কোনও বিষয়তে "কারেন্টথিং" এর সাথে আবদ্ধ।

ট্রিভিউ থেকে আমার মডেলটিতে একটি দুর্দান্ত বাঁধন সমর্থন করার জন্য প্রয়োজনীয় অতিরিক্ত পদক্ষেপগুলি (যেমন: কাস্টম আচরণ, তৃতীয় পক্ষের নিয়ন্ত্রণ) অতিক্রম করার পরিবর্তে এবং তারপরে আমার মডেলের অন্য কিছু থেকে, আমার সমাধানটি ছিল অন্য উপাদানটির সাথে আবদ্ধ হওয়া সাধারণ উপাদানটি ব্যবহার করা was আমার ভিউমোডেলের সাথে অন্য জিনিসটিকে আবদ্ধ করার পরিবর্তে ট্রিভিউ.সিলিগ্রেটেড আইটেম, যার ফলে প্রয়োজনীয় অতিরিক্ত কাজটি বাদ দেওয়া হয়।

XAML:

<TreeView x:Name="myTreeView" ItemsSource="{Binding MyThingyCollection}">
.... stuff
</TreeView>

<!-- then.. somewhere else where I want to see the currently selected TreeView item: -->

<local:MyThingyDetailsView 
       DataContext="{Binding ElementName=myTreeView, Path=SelectedItem}" />

অবশ্যই, এটি বর্তমানে নির্বাচিত আইটেমটি পড়ার জন্য দুর্দান্ত তবে এটি সেট করা নেই, যা আমার প্রয়োজন কেবল।


1
স্থানীয় কী: মাইথিঙ্গিডিটেলভিউ? আমি সেই লোকালটি পাই: মাইথিংগিডিটেলভিউ ভিউ নির্বাচিত আইটেমটি ধারণ করে তবে আপনার ভিউ মডেল কীভাবে এই তথ্যটি পাবেন? এটি করার মতো এটি দুর্দান্ত, পরিষ্কার পদ্ধতির মতো দেখায়, তবে আমার আরও কিছুটা তথ্য প্রয়োজন ...
বব হর্ন

স্থানীয়: মাইথিঙ্গিডিটেলভিউ ভিউ হ'ল এক্সএএমএল পূর্ণ একটি ইউজার কনট্রোল যা একটি "জিনিসযুক্ত" উদাহরণ সম্পর্কে বিশদ বিবরণ তৈরি করে। এটি সামগ্রী হিসাবে অন্য ভিউয়ের মাঝখানে এম্বেড করা হয়েছে, ডাব্লু / এই ভিউটির ডেটা কনটেক্সটটি এলিমেন্ট বাইন্ডিং ব্যবহার করে বর্তমানে নির্বাচিত ট্রি ভিউ আইটেম।
ওয়েজ

6

আপনি ট্রিভিউআইটেম.আইএসসলেক্টেড প্রপার্টিটি ব্যবহার করতে সক্ষম হতে পারেন


আমি মনে করি এটি সঠিক উত্তর হতে পারে। তবে আমি আইটেমগুলির ইসসলেক্টেড সম্পত্তিটি ট্রিভিউতে কীভাবে দেওয়া হবে তার একটি উদাহরণ বা সেরা-অনুশীলনের পুনরুদ্ধার দেখতে চাই।
আনহপ্প

3

ইন্টারঅ্যাকশন.বিহেভিয়ার্স ব্যবহার না করে এক্সএএমএল বাইন্ডেবল সিলেক্টড আইটেম সম্পত্তি তৈরি করার একটি উপায়ও রয়েছে।

public static class BindableSelectedItemHelper
{
    #region Properties

    public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.RegisterAttached("SelectedItem", typeof(object), typeof(BindableSelectedItemHelper),
        new FrameworkPropertyMetadata(null, OnSelectedItemPropertyChanged));

    public static readonly DependencyProperty AttachProperty = DependencyProperty.RegisterAttached("Attach", typeof(bool), typeof(BindableSelectedItemHelper), new PropertyMetadata(false, Attach));

    private static readonly DependencyProperty IsUpdatingProperty = DependencyProperty.RegisterAttached("IsUpdating", typeof(bool), typeof(BindableSelectedItemHelper));

    #endregion

    #region Implementation

    public static void SetAttach(DependencyObject dp, bool value)
    {
        dp.SetValue(AttachProperty, value);
    }

    public static bool GetAttach(DependencyObject dp)
    {
        return (bool)dp.GetValue(AttachProperty);
    }

    public static string GetSelectedItem(DependencyObject dp)
    {
        return (string)dp.GetValue(SelectedItemProperty);
    }

    public static void SetSelectedItem(DependencyObject dp, object value)
    {
        dp.SetValue(SelectedItemProperty, value);
    }

    private static bool GetIsUpdating(DependencyObject dp)
    {
        return (bool)dp.GetValue(IsUpdatingProperty);
    }

    private static void SetIsUpdating(DependencyObject dp, bool value)
    {
        dp.SetValue(IsUpdatingProperty, value);
    }

    private static void Attach(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        TreeListView treeListView = sender as TreeListView;
        if (treeListView != null)
        {
            if ((bool)e.OldValue)
                treeListView.SelectedItemChanged -= SelectedItemChanged;

            if ((bool)e.NewValue)
                treeListView.SelectedItemChanged += SelectedItemChanged;
        }
    }

    private static void OnSelectedItemPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        TreeListView treeListView = sender as TreeListView;
        if (treeListView != null)
        {
            treeListView.SelectedItemChanged -= SelectedItemChanged;

            if (!(bool)GetIsUpdating(treeListView))
            {
                foreach (TreeViewItem item in treeListView.Items)
                {
                    if (item == e.NewValue)
                    {
                        item.IsSelected = true;
                        break;
                    }
                    else
                       item.IsSelected = false;                        
                }
            }

            treeListView.SelectedItemChanged += SelectedItemChanged;
        }
    }

    private static void SelectedItemChanged(object sender, RoutedEventArgs e)
    {
        TreeListView treeListView = sender as TreeListView;
        if (treeListView != null)
        {
            SetIsUpdating(treeListView, true);
            SetSelectedItem(treeListView, treeListView.SelectedItem);
            SetIsUpdating(treeListView, false);
        }
    }
    #endregion
}

তারপরে আপনি এটি আপনার এক্সএএমএল হিসাবে এটি ব্যবহার করতে পারেন:

<TreeView  helper:BindableSelectedItemHelper.Attach="True" 
           helper:BindableSelectedItemHelper.SelectedItem="{Binding SelectedItem, Mode=TwoWay}">

3

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

public class TreeViewEx : TreeView
{
    public TreeViewEx()
    {
        this.SelectedItemChanged += new RoutedPropertyChangedEventHandler<object>(TreeViewEx_SelectedItemChanged);
    }

    void TreeViewEx_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
    {
        this.SelectedItem = e.NewValue;
    }

    #region SelectedItem

    /// <summary>
    /// Gets or Sets the SelectedItem possible Value of the TreeViewItem object.
    /// </summary>
    public new object SelectedItem
    {
        get { return this.GetValue(TreeViewEx.SelectedItemProperty); }
        set { this.SetValue(TreeViewEx.SelectedItemProperty, value); }
    }

    // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
    public new static readonly DependencyProperty SelectedItemProperty =
        DependencyProperty.Register("SelectedItem", typeof(object), typeof(TreeViewEx),
        new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, SelectedItemProperty_Changed));

    static void SelectedItemProperty_Changed(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
    {
        TreeViewEx targetObject = dependencyObject as TreeViewEx;
        if (targetObject != null)
        {
            TreeViewItem tvi = targetObject.FindItemNode(targetObject.SelectedItem) as TreeViewItem;
            if (tvi != null)
                tvi.IsSelected = true;
        }
    }                                               
    #endregion SelectedItem   

    public TreeViewItem FindItemNode(object item)
    {
        TreeViewItem node = null;
        foreach (object data in this.Items)
        {
            node = this.ItemContainerGenerator.ContainerFromItem(data) as TreeViewItem;
            if (node != null)
            {
                if (data == item)
                    break;
                node = FindItemNodeInChildren(node, item);
                if (node != null)
                    break;
            }
        }
        return node;
    }

    protected TreeViewItem FindItemNodeInChildren(TreeViewItem parent, object item)
    {
        TreeViewItem node = null;
        bool isExpanded = parent.IsExpanded;
        if (!isExpanded) //Can't find child container unless the parent node is Expanded once
        {
            parent.IsExpanded = true;
            parent.UpdateLayout();
        }
        foreach (object data in parent.Items)
        {
            node = parent.ItemContainerGenerator.ContainerFromItem(data) as TreeViewItem;
            if (data == item && node != null)
                break;
            node = FindItemNodeInChildren(node, item);
            if (node != null)
                break;
        }
        if (node == null && parent.IsExpanded != isExpanded)
            parent.IsExpanded = isExpanded;
        if (node != null)
            parent.IsExpanded = true;
        return node;
    }
} 

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

3

আমার প্রয়োজন PRISM-MVVM ভিত্তিক সমাধানের জন্য যেখানে একটি ট্রিভিউয়ের প্রয়োজন ছিল এবং আবদ্ধ অবজেক্টটি সংগ্রহের ধরণের হয় <> এবং তাই হায়ারার্কিকাল ডেটাটিম্পলেট প্রয়োজন। ডিফল্ট বাইন্ডেবলসিলেক্টড আইটেম বিহেভিয়ার শিশু ট্রিভিউআইটেম সনাক্ত করতে সক্ষম হবে না। এটি এই পরিস্থিতিতে কাজ করতে।

public class BindableSelectedItemBehavior : Behavior<TreeView>
{
    #region SelectedItem Property

    public object SelectedItem
    {
        get { return (object)GetValue(SelectedItemProperty); }
        set { SetValue(SelectedItemProperty, value); }
    }

    public static readonly DependencyProperty SelectedItemProperty =
        DependencyProperty.Register("SelectedItem", typeof(object), typeof(BindableSelectedItemBehavior), new UIPropertyMetadata(null, OnSelectedItemChanged));

    private static void OnSelectedItemChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        var behavior = sender as BindableSelectedItemBehavior;
        if (behavior == null) return;
        var tree = behavior.AssociatedObject;
        if (tree == null) return;
        if (e.NewValue == null)
            foreach (var item in tree.Items.OfType<TreeViewItem>())
                item.SetValue(TreeViewItem.IsSelectedProperty, false);
        var treeViewItem = e.NewValue as TreeViewItem;
        if (treeViewItem != null)
            treeViewItem.SetValue(TreeViewItem.IsSelectedProperty, true);
        else
        {
            var itemsHostProperty = tree.GetType().GetProperty("ItemsHost", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
            if (itemsHostProperty == null) return;
            var itemsHost = itemsHostProperty.GetValue(tree, null) as Panel;
            if (itemsHost == null) return;
            foreach (var item in itemsHost.Children.OfType<TreeViewItem>())
            {
                if (WalkTreeViewItem(item, e.NewValue)) 
                    break;
            }
        }
    }

    public static bool WalkTreeViewItem(TreeViewItem treeViewItem, object selectedValue)
    {
        if (treeViewItem.DataContext == selectedValue)
        {
            treeViewItem.SetValue(TreeViewItem.IsSelectedProperty, true);
            treeViewItem.Focus();
            return true;
        }
        var itemsHostProperty = treeViewItem.GetType().GetProperty("ItemsHost", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
        if (itemsHostProperty == null) return false;
        var itemsHost = itemsHostProperty.GetValue(treeViewItem, null) as Panel;
        if (itemsHost == null) return false;
        foreach (var item in itemsHost.Children.OfType<TreeViewItem>())
        {
            if (WalkTreeViewItem(item, selectedValue))
                break;
        }
        return false;
    }
    #endregion

    protected override void OnAttached()
    {
        base.OnAttached();
        this.AssociatedObject.SelectedItemChanged += OnTreeViewSelectedItemChanged;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        if (this.AssociatedObject != null)
        {
            this.AssociatedObject.SelectedItemChanged -= OnTreeViewSelectedItemChanged;
        }
    }

    private void OnTreeViewSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
    {
        this.SelectedItem = e.NewValue;
    }
}

স্তরটি নির্বিশেষে সমস্ত উপাদানগুলির মাধ্যমে এটি পুনরাবৃত্তি করতে সক্ষম করে।


ধন্যবাদ! এটিই কেবলমাত্র আমার দৃশ্যের জন্য কাজ করে যা আপনার মত নয়।
রবার্ট

খুব ভাল কাজ করে এবং নির্বাচিত / প্রসারিত বাইন্ডিংগুলিকে গুলিয়ে ফেলবে না
মরিচা

2

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

private static void OnSelectedItemChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        var behavior = sender as BindableSelectedItemBehaviour;

        if (behavior == null) return;

        var tree = behavior.AssociatedObject;

        if (tree == null) return;

        if (e.NewValue == null) 
            foreach (var item in tree.Items.OfType<TreeViewItem>())
                item.SetValue(TreeViewItem.IsSelectedProperty, false);

        var treeViewItem = e.NewValue as TreeViewItem; 
        if (treeViewItem != null)
        {
            treeViewItem.SetValue(TreeViewItem.IsSelectedProperty, true);
        }
        else
        {
            var itemsHostProperty = tree.GetType().GetProperty("ItemsHost", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);

            if (itemsHostProperty == null) return;

            var itemsHost = itemsHostProperty.GetValue(tree, null) as Panel;

            if (itemsHost == null) return;

            foreach (var item in itemsHost.Children.OfType<TreeViewItem>())
                if (WalkTreeViewItem(item, e.NewValue)) break;
        }
    }

    public static bool WalkTreeViewItem(TreeViewItem treeViewItem, object selectedValue) {
        if (treeViewItem.DataContext == selectedValue)
        {
            treeViewItem.SetValue(TreeViewItem.IsSelectedProperty, true);
            treeViewItem.Focus();
            return true;
        }

        foreach (var item in treeViewItem.Items.OfType<TreeViewItem>())
            if (WalkTreeViewItem(item, selectedValue)) return true;

        return false;
    }

এই উপায়টি দ্বি-মুখী বাঁধনের জন্য কাজ করে। বিকল্পভাবে, আইটেমহস্ট অধিগ্রহণটি আচরণের অনাচড পদ্ধতিতে স্থানান্তরিত করা সম্ভব, প্রতিবারের বাধ্যতামূলক আপডেটগুলি প্রতিচ্ছবি ব্যবহারের ওভারহেড সংরক্ষণ করা।


2

ডাব্লুপিএফ এমভিভিএম ট্রিভিউ সিলেক্ট আইটেম

... এটি একটি উত্তম উত্তর, তবে ভিউমোডেলে নির্বাচিত আইটেমটি / সেট করার কোনও উপায় উল্লেখ করে না mention

  1. আপনার আইটেমভিউমোডেলে একটি ইসসলেক্টড বুলিয়ান সম্পত্তি যুক্ত করুন এবং এর সাথে ট্রিভিউআইটেমের জন্য একটি স্টাইল সেটারে আবদ্ধ করুন।
  2. ট্রিভিউয়ের ডেটা কনটেক্সট হিসাবে ব্যবহৃত আপনার ভিউমোডেলে একটি নির্বাচিত আইটেম সম্পত্তি যুক্ত করুন। এটি উপরের সমাধানটিতে অনুপস্থিত অংশ।
    'আইটেমভিএম ...
    সরকারী সম্পত্তি বুলিয়ান হিসাবে নির্বাচিত
        পাওয়া
            ফিরে আসুন_ফানক.সিলেক্টড নোড ইজ মি
        শেষ পান
        সেট করুন (বুলিয়ান হিসাবে মান)
            যদি ইসসলেক্টেড মান হয় তবে
                _ফানস.সিলেক্টড নোড = যদি (মান, আমার কিছুই না)
            যদি শেষ
            RaisePropertyChange ()
        সমাপ্তি সেট
    শেষ সম্পত্তি
    'ট্রিভিএম ...
    আইটেমভিএম হিসাবে সরকারী সম্পত্তি নির্বাচিত আইটেম tem
        পাওয়া
            প্রত্যাবর্তন _ছবিযুক্ত আইটেম
        শেষ পান
        সেট করুন (আইটেমভিএম হিসাবে মান)
            _সलेक्ट করা আইটেম যদি মান হয় তবে
                প্রত্যাবর্তন
            যদি শেষ
            ধীর পূর্ব = _ নির্বাচিত আইটেম
            _নির্বাচিত আইটেম = মান
            যদি প্রিপ ইসনট নথিং এরপরে না
                prev.IsSelected = মিথ্যা
            যদি শেষ
            যদি _সেইলেটেড আইটেম ইসন না হয় কিছুই না
                _সিলেক্ট আইটেম.আইএসলেকড = সত্য
            যদি শেষ
        সমাপ্তি সেট
    শেষ সম্পত্তি
<TreeView ItemsSource="{Binding Path=TreeVM}" 
          BorderBrush="Transparent">
    <TreeView.ItemContainerStyle>
        <Style TargetType="TreeViewItem">
            <Setter Property="IsExpanded" Value="{Binding IsExpanded}"/>
            <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
        </Style>
    </TreeView.ItemContainerStyle>
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding Children}">
            <TextBlock Text="{Binding Name}"/>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

1

একদিনের জন্য ইন্টারনেট অধ্যয়ন করার পরে আমি একটি সাধারণ ডাব্লুপিএফ / সি # পরিবেশে একটি সাধারণ ট্রিভিউ তৈরি করার পরে কোনও আইটেম নির্বাচন করার জন্য আমার নিজের সমাধানটি পেয়েছি

private void BuildSortTree(int sel)
        {
            MergeSort.Items.Clear();
            TreeViewItem itTemp = new TreeViewItem();
            itTemp.Header = SortList[0];
            MergeSort.Items.Add(itTemp);
            TreeViewItem prev;
            itTemp.IsExpanded = true;
            if (0 == sel) itTemp.IsSelected= true;
            prev = itTemp;
            for(int i = 1; i<SortList.Count; i++)
            {

                TreeViewItem itTempNEW = new TreeViewItem();
                itTempNEW.Header = SortList[i];
                prev.Items.Add(itTempNEW);
                itTempNEW.IsExpanded = true;
                if (i == sel) itTempNEW.IsSelected = true;
                prev = itTempNEW ;
            }
        }

1

এটি ট্রিভিউ আইটেমের ইস্প্লেটেড সম্পত্তি ব্যবহার করেও করা যেতে পারে। আমি কীভাবে এটি পরিচালনা করেছি তা এখানে,

public delegate void TreeviewItemSelectedHandler(TreeViewItem item);
public class TreeViewItem
{      
  public static event TreeviewItemSelectedHandler OnItemSelected = delegate { };
  public bool IsSelected 
  {
    get { return isSelected; }
    set 
    { 
      isSelected = value;
      if (value)
        OnItemSelected(this);
    }
  }
}

তারপরে ভিউমোডলে যাতে আপনার ট্রিভিউউ আবদ্ধ ডেটা ধারণ করে, কেবল ট্রিভিউআইটিম ক্লাসে ইভেন্টটির সদস্যতা নিন।

TreeViewItem.OnItemSelected += TreeViewItemSelected;

এবং অবশেষে, একই ভিউমোডেলে এই হ্যান্ডলারটি প্রয়োগ করুন,

private void TreeViewItemSelected(TreeViewItem item)
{
  //Do something
}

এবং অবশ্যই বাঁধাই,

<Setter Property="IsSelected" Value="{Binding IsSelected}" />    

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

1

আমি জানি এই থ্রেডটি 10 ​​বছর পুরানো তবে সমস্যাটি এখনও রয়েছে ....

মূল প্রশ্নটি ছিল নির্বাচিত আইটেমটি 'পুনরুদ্ধার করা'। আমার ভিউ মডেলটিতে নির্বাচিত আইটেমটি "পাওয়ার" দরকারও ছিল (সেট করে নেই)। এই থ্রেডের সমস্ত উত্তরগুলির মধ্যে, 'ওয়েস' দ্বারা দেওয়া একটিই সেই সমস্যাটিকে ভিন্নভাবে পৌঁছে দেয়: আপনি যদি 'নির্বাচিত আইটেমটি' ডেটাবাইন্ডিংয়ের লক্ষ্য হিসাবে ব্যবহার করতে পারেন তবে এটি ডেটাবাইন্ডিংয়ের উত্স হিসাবে ব্যবহার করুন। ওয়েস এটি অন্য দেখার সম্পত্তিতে করেছে, আমি এটি একটি ভিউমডেল সম্পত্তিতে করব:

আমাদের দুটি জিনিস দরকার:

  • ভিউমোডলে একটি নির্ভরতা সম্পত্তি তৈরি করুন (আমার মাইবাজেক্টের ধরণের ক্ষেত্রে আমার ট্রিউভিউ 'মাইবজেক্ট' টাইপের অবজেক্টের সাথে আবদ্ধ)
  • ট্রিভিউ থেকে বাঁধুন.ভিউ এর কনস্ট্রাক্টরে এই সম্পত্তিটির জন্য নির্বাচিত আইটেমটি সংযুক্ত করুন (হ্যাঁ এটি পিছনের কোড তবে, সম্ভবত আপনি সেখানেও আপনার ডেটা কনটেক্সট শুরু করবেন)

Viewmodel:

public static readonly DependencyProperty SelectedTreeViewItemProperty = DependencyProperty.Register("SelectedTreeViewItem", typeof(MyObject), typeof(MyViewModel), new PropertyMetadata(OnSelectedTreeViewItemChanged));

    private static void OnSelectedTreeViewItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        (d as MyViewModel).OnSelectedTreeViewItemChanged(e);
    }

    private void OnSelectedTreeViewItemChanged(DependencyPropertyChangedEventArgs e)
    {
        //do your stuff here
    }

    public MyObject SelectedWorkOrderTreeViewItem
    {
        get { return (MyObject)GetValue(SelectedTreeViewItemProperty); }
        set { SetValue(SelectedTreeViewItemProperty, value); }
    }

নির্মাতা দেখুন:

Binding binding = new Binding("SelectedItem")
        {
            Source = treeView, //name of tree view in xaml
            Mode = BindingMode.OneWay
        };

        BindingOperations.SetBinding(DataContext, MyViewModel.SelectedTreeViewItemProperty, binding);

0

(আসুন আমরা সকলেই সম্মত হই যে ট্রিউভিউ এই সমস্যাটির বিষয়ে স্পষ্টতই ধামাচাপা পড়েছে Se নির্বাচিত আইটেমের সাথে বাঁধাই সুস্পষ্ট হত S দীর্ঘশ্বাস )

ট্রিভিউআইটিমের আইসলেক্টেড প্রোপার্টিটির সাথে সঠিকভাবে যোগাযোগ করার জন্য আমার সমাধানটির প্রয়োজন ছিল, তাই আমি কীভাবে এটি করেছি তা এখানে:

// the Type CustomThing needs to implement IsSelected with notification
// for this to work.
public class CustomTreeView : TreeView
{
    public CustomThing SelectedCustomThing
    {
        get
        {
            return (CustomThing)GetValue(SelectedNode_Property);
        }
        set
        {
            SetValue(SelectedNode_Property, value);
            if(value != null) value.IsSelected = true;
        }
    }

    public static DependencyProperty SelectedNode_Property =
        DependencyProperty.Register(
            "SelectedCustomThing",
            typeof(CustomThing),
            typeof(CustomTreeView),
            new FrameworkPropertyMetadata(
                null,
                FrameworkPropertyMetadataOptions.None,
                SelectedNodeChanged));

    public CustomTreeView(): base()
    {
        this.SelectedItemChanged += new RoutedPropertyChangedEventHandler<object>(SelectedItemChanged_CustomHandler);
    }

    void SelectedItemChanged_CustomHandler(object sender, RoutedPropertyChangedEventArgs<object> e)
    {
        SetValue(SelectedNode_Property, SelectedItem);
    }

    private static void SelectedNodeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var treeView = d as CustomTreeView;
        var newNode = e.NewValue as CustomThing;

        treeView.SelectedCustomThing = (CustomThing)e.NewValue;
    }
}

এই এক্সএএমএল সহ:

<local:CustonTreeView ItemsSource="{Binding TreeRoot}" 
    SelectedCustomThing="{Binding SelectedNode,Mode=TwoWay}">
    <TreeView.ItemContainerStyle>
        <Style TargetType="TreeViewItem">
            <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
        </Style>
    </TreeView.ItemContainerStyle>
</local:CustonTreeView>

0

আমি আপনার জন্য আমার সমাধান নিয়ে আসছি যা নিম্নলিখিত বৈশিষ্ট্যগুলি সরবরাহ করে:

  • 2 উপায় বাঁধাই সমর্থন করে

  • TreeViewItem.IsS নির্বাচিত বৈশিষ্ট্যগুলি (নির্বাচিত আইটেম অনুসারে) স্বয়ংক্রিয়ভাবে আপডেট হয়

  • ট্রিভিউউ সাবক্লাসিং নেই

  • ভিউমোডেলের সাথে আবদ্ধ আইটেমগুলি যে কোনও ধরণের হতে পারে (এমনকি নালও)

1 / আপনার সিএসে নিম্নলিখিত কোডটি আটকান:

public class BindableSelectedItem
{
    public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.RegisterAttached(
        "SelectedItem", typeof(object), typeof(BindableSelectedItem), new PropertyMetadata(default(object), OnSelectedItemPropertyChangedCallback));

    private static void OnSelectedItemPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var treeView = d as TreeView;
        if (treeView != null)
        {
            BrowseTreeViewItems(treeView, tvi =>
            {
                tvi.IsSelected = tvi.DataContext == e.NewValue;
            });
        }
        else
        {
            throw new Exception("Attached property supports only TreeView");
        }
    }

    public static void SetSelectedItem(DependencyObject element, object value)
    {
        element.SetValue(SelectedItemProperty, value);
    }

    public static object GetSelectedItem(DependencyObject element)
    {
        return element.GetValue(SelectedItemProperty);
    }

    public static void BrowseTreeViewItems(TreeView treeView, Action<TreeViewItem> onBrowsedTreeViewItem)
    {
        var collectionsToVisit = new System.Collections.Generic.List<Tuple<ItemContainerGenerator, ItemCollection>> { new Tuple<ItemContainerGenerator, ItemCollection>(treeView.ItemContainerGenerator, treeView.Items) };
        var collectionIndex = 0;
        while (collectionIndex < collectionsToVisit.Count)
        {
            var itemContainerGenerator = collectionsToVisit[collectionIndex].Item1;
            var itemCollection = collectionsToVisit[collectionIndex].Item2;
            for (var i = 0; i < itemCollection.Count; i++)
            {
                var tvi = itemContainerGenerator.ContainerFromIndex(i) as TreeViewItem;
                if (tvi == null)
                {
                    continue;
                }

                if (tvi.ItemContainerGenerator.Status == System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated)
                {
                    collectionsToVisit.Add(new Tuple<ItemContainerGenerator, ItemCollection>(tvi.ItemContainerGenerator, tvi.Items));
                }

                onBrowsedTreeViewItem(tvi);
            }

            collectionIndex++;
        }
    }

}

2 / আপনার এক্সএএমএল ফাইলটিতে ব্যবহারের উদাহরণ

<TreeView myNS:BindableSelectedItem.SelectedItem="{Binding Path=SelectedItem, Mode=TwoWay}" />  

0

আমি এই সমাধানটির প্রস্তাব দিই (যা আমি সবচেয়ে সহজ এবং মেমরির ফাঁস মুক্ত বলে বিবেচনা করি) যা ভিউ নির্বাচিত আইটেম থেকে ভিউমোডেলের নির্বাচিত আইটেমটি আপডেট করার জন্য পুরোপুরি কাজ করে।

দয়া করে নোট করুন যে ভিউমোডেল থেকে নির্বাচিত আইটেমটি পরিবর্তন করা দৃশ্যটির নির্বাচিত আইটেমটি আপডেট করবে না।

public class TreeViewEx : TreeView
{
    public static readonly DependencyProperty SelectedItemExProperty = DependencyProperty.Register("SelectedItemEx", typeof(object), typeof(TreeViewEx), new FrameworkPropertyMetadata(default(object))
    {
        BindsTwoWayByDefault = true // Required in order to avoid setting the "BindingMode" from the XAML
    });

    public object SelectedItemEx
    {
        get => GetValue(SelectedItemExProperty);
        set => SetValue(SelectedItemExProperty, value);
    }

    protected override void OnSelectedItemChanged(RoutedPropertyChangedEventArgs<object> e)
    {
        SelectedItemEx = e.NewValue;
    }
}

এক্সএএমএল ব্যবহার

<l:TreeViewEx ItemsSource="{Binding Path=Items}" SelectedItemEx="{Binding Path=SelectedItem}" >
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.