কনটেক্সটমেনু প্রদর্শিত হওয়ার ঠিক আগে ডান ক্লিকে ডাব্লুপিএফ ট্রিভিউ নোডটি নির্বাচন করতে চাই।
উইনফোর্ডসের জন্য আমি প্রসঙ্গ মেনুতে ক্লিক করা এই ফাইন্ড নোডের মতো কোড ব্যবহার করতে পারি, ডাব্লুপিএফ বিকল্পগুলি কী?
কনটেক্সটমেনু প্রদর্শিত হওয়ার ঠিক আগে ডান ক্লিকে ডাব্লুপিএফ ট্রিভিউ নোডটি নির্বাচন করতে চাই।
উইনফোর্ডসের জন্য আমি প্রসঙ্গ মেনুতে ক্লিক করা এই ফাইন্ড নোডের মতো কোড ব্যবহার করতে পারি, ডাব্লুপিএফ বিকল্পগুলি কী?
উত্তর:
গাছটি যেভাবে জনবহুল হয়েছিল তার উপর নির্ভর করে প্রেরক এবং ই-উত্সের মানগুলি পৃথক হতে পারে ।
সম্ভাব্য সমাধানগুলির মধ্যে একটি হ'ল ই.আরিনালসোর্স ব্যবহার করা এবং ভিজ্যুয়ালটিহেল্পার ব্যবহার করে ট্রিভিউআইটেমটি সন্ধান করা:
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;
}
if (treeViewItem == null) treeView.SelectedIndex = -1
বা treeView.SelectedItem = null
। আমি বিশ্বাস করি হয় কাজ করা উচিত।
আপনি যদি এক্সএএমএল-কেবল সমাধান চান তবে আপনি মিশ্রিত ইন্টারেক্টিভিটি ব্যবহার করতে পারেন।
ধরে 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>
দুটি আকর্ষণীয় অংশ রয়েছে:
TreeViewItem.IsSelected
সম্পত্তি আবদ্ধ হয় IsSelected
দেখার মডেলের উপর সম্পত্তি। IsSelected
ভিউ-মডেলটিতে সম্পত্তিটিকে সত্যে সেট করা গাছের সাথে সম্পর্কিত নোডটি নির্বাচন করবে।
যখন PreviewMouseRightButtonDown
নোড (এই নমুনা একটি চাক্ষুষ পক্ষ থেকে দাবানল TextBlock
) IsSelected
দর্শনযোগ্য মডেলের উপর সম্পত্তি সত্যতে সেট করা থাকে। ১ এ ফিরে যান আপনি দেখতে পাচ্ছেন যে গাছে ক্লিক করা সংশ্লিষ্ট নোডটি নির্বাচিত নোড হয়ে যায়।
ওয়ান ওয়ে আপনার প্রকল্পের মিশান ইন্ট্যার্যাক্টিভিটির পেতে NuGet প্যাকেজ ব্যবহার করা Unofficial.Blend.Interactivity ।
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 সমাবেশগুলিতে পাওয়া যায়।
ChangePropertyAction
একটি IsSelected
সম্পত্তি সেট করার চেষ্টা করছে যা ইউআইয়ের অংশ নয়, সুতরাং এর IsSelected
সম্পত্তি নেই। আমি কি ভুল কিছু করছি?
IsSelected
আমার উত্তরের দ্বিতীয় অনুচ্ছেদে বর্ণিত একটি সম্পত্তি আছে : ধরে নিন যে বুলিয়ান সম্পত্তি সম্বলিতTreeView
ভিউ-মডেলগুলির একটি শ্রেণিবদ্ধ সংগ্রহের সাথে আবদ্ধ ডেটা ...IsSelected
(আমার জোর)
এক্সএএমএল-এ, এক্সএএমএল-এ একটি পূর্বরূপমাউস রাইটবাটনডাউন হ্যান্ডলার যুক্ত করুন:
<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;
}
}
অ্যালেক্স 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;
}
সম্পাদনা: পূর্ববর্তী কোডটি এই দৃশ্যের জন্য সর্বদা সূক্ষ্মভাবে কাজ করেছিল, তবে অন্য দৃশ্যে ভিজুয়ালটি ট্রিহেল্পার.গেটপ্যারেন্ট নালাগুলি প্রত্যাবর্তন করেছে যখন লজিক্যাল ট্রিহেল্পার একটি মান ফিরিয়ে দেয়, তাই এটি স্থির করে দেওয়া হয়েছিল।
প্রায় ডানদিকে , তবে আপনার গাছের অ-ভিজ্যুয়ালগুলি লক্ষ্য করা দরকার ( 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;
}
আমি মনে করি একটি ক্লাস হ্যান্ডলারের নিবন্ধকরণের কৌশলটি করা উচিত। আপনার 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;
}
}
এমভিভিএম ব্যবহার করে এটি সমাধানের আরেকটি উপায় হ'ল আপনার ভিউ মডেলের ডান ক্লিকের জন্য বাইন্ড কমান্ড। সেখানে আপনি অন্যান্য যুক্তিও নির্দিষ্ট করতে পারেন source.IsSelected = true
। এটি কেবল xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
থেকে ব্যবহার করে 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;
}
}
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
। যেহেতু শিশুটিকে প্রথম বলা হয়। এই সম্পত্তিটিকে সত্যে সেটিংস করা পিতামাতার কাছে অন্য কলগুলি অক্ষম করে।
আপনি এটি মাউস ডাউন ইভেন্টের সাহায্যে নির্বাচন করতে পারেন। কনটেক্সট মেনুতে কিক করার আগে এটি নির্বাচনকে ট্রিগার করবে।
আপনি যদি এমভিভিএম প্যাটার্নের মধ্যে থাকতে চান তবে আপনি নিম্নলিখিতটি করতে পারেন:
দেখুন:
<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>