আমি উইন্ডোতে সমস্ত ধরণের নিয়ন্ত্রণগুলি তাদের ধরণের মাধ্যমে সন্ধান করার জন্য একটি উপায় খুঁজছি,
উদাহরণস্বরূপ: সমস্ত অনুসন্ধান করুন TextBoxes
, নির্দিষ্ট ইন্টারফেস প্রয়োগকারী সমস্ত নিয়ন্ত্রণ সন্ধান করুন etc.
আমি উইন্ডোতে সমস্ত ধরণের নিয়ন্ত্রণগুলি তাদের ধরণের মাধ্যমে সন্ধান করার জন্য একটি উপায় খুঁজছি,
উদাহরণস্বরূপ: সমস্ত অনুসন্ধান করুন TextBoxes
, নির্দিষ্ট ইন্টারফেস প্রয়োগকারী সমস্ত নিয়ন্ত্রণ সন্ধান করুন etc.
উত্তর:
এই কৌতুক করতে হবে
public static IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
তারপরে আপনি নিয়ন্ত্রণগুলি ওঠান
foreach (TextBlock tb in FindVisualChildren<TextBlock>(window))
{
// do something with tb here
}
this
আগে DependencyObject
=> সন্নিবেশ করে এটি একটি এক্সটেনশন পদ্ধতিতে পরিণত করবthis DependencyObject depObj
এই সবচেয়ে সহজ উপায়:
IEnumerable<myType> collection = control.Children.OfType<myType>();
যেখানে নিয়ন্ত্রণ উইন্ডোর মূল উপাদান।
<Grid Name="Anata_wa_yoru_o_shihai_suru_ai">here buttons</Grid>
এবং তারপরে আমি ব্যবহার করতে পারিAnata_wa_yoru_o_shihai_suru_ai.Children.OfType<myType>();
আমি @ ব্রায়স কাহেলের জবাবটি @ ম্যাথিয়াস লাইককেগার্ড লরেঞ্জেনের পরামর্শ এবং ব্যবহার অনুসরণ করতে মানিয়েছি LogicalTreeHelper
।
ঠিক আছে কাজ মনে হচ্ছে। ;)
public static IEnumerable<T> FindLogicalChildren<T> ( DependencyObject depObj ) where T : DependencyObject
{
if( depObj != null )
{
foreach( object rawChild in LogicalTreeHelper.GetChildren( depObj ) )
{
if( rawChild is DependencyObject )
{
DependencyObject child = (DependencyObject)rawChild;
if( child is T )
{
yield return (T)child;
}
foreach( T childOfChild in FindLogicalChildren<T>( child ) )
{
yield return childOfChild;
}
}
}
}
}
(এটি এখনও যথাক্রমে @ বেঞ্জামিন বেরি এবং @ ডেভিড আর দ্বারা উল্লিখিত গ্রুপবক্সের ভিতরে ট্যাব নিয়ন্ত্রণ বা গ্রিড পরীক্ষা করে না))
সাহায্যকারী শ্রেণীর ব্যবহার করুন VisualTreeHelper
বা LogicalTreeHelper
নির্ভর যার উপর গাছ আপনি আগ্রহী করছি। তারা উভয় একটি উপাদান সন্তান পাবার জন্য পদ্ধতি প্রদান (যদিও সিনট্যাক্স একটু আলাদা)। আমি প্রায়শই নির্দিষ্ট ধরণের প্রথম উপস্থিতি সন্ধানের জন্য এই ক্লাসগুলি ব্যবহার করি তবে আপনি এই ধরণের সমস্ত অবজেক্ট সন্ধান করতে সহজেই এটিকে সংশোধন করতে পারেন:
public static DependencyObject FindInVisualTreeDown(DependencyObject obj, Type type)
{
if (obj != null)
{
if (obj.GetType() == type)
{
return obj;
}
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject childReturn = FindInVisualTreeDown(VisualTreeHelper.GetChild(obj, i), type);
if (childReturn != null)
{
return childReturn;
}
}
}
return null;
}
আমি দেখতে পেয়েছি যে VisualTreeHelper.GetChildrenCount(depObj);
উপরের কয়েকটি উদাহরণে ব্যবহৃত লাইনটি GroupBox
এস এর জন্য একটি শূন্য-গণনা প্রদান করে না , বিশেষত যেখানে GroupBox
একটিতে রয়েছে Grid
এবং Grid
এতে শিশুদের উপাদান রয়েছে। আমি বিশ্বাস করি এটি এর কারণ হতে পারে কারণ GroupBox
একাধিক শিশুকে ধারণ করার অনুমতি নেই এবং এটি তার Content
সম্পত্তিতে সঞ্চিত রয়েছে । কোনও GroupBox.Children
ধরণের সম্পত্তি নেই। আমি নিশ্চিত যে আমি এটি খুব দক্ষতার সাথে করিনি, তবে আমি এই চেইনে প্রথম "FindVisualChildren" উদাহরণটি নিম্নরূপে সংশোধন করেছি:
public IEnumerable<T> FindVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
int depObjCount = VisualTreeHelper.GetChildrenCount(depObj);
for (int i = 0; i <depObjCount; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
if (child is GroupBox)
{
GroupBox gb = child as GroupBox;
Object gpchild = gb.Content;
if (gpchild is T)
{
yield return (T)child;
child = gpchild as T;
}
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
নির্দিষ্ট ধরণের সমস্ত সন্তানের একটি তালিকা পেতে আপনি ব্যবহার করতে পারেন:
private static IEnumerable<DependencyObject> FindInVisualTreeDown(DependencyObject obj, Type type)
{
if (obj != null)
{
if (obj.GetType() == 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;
}
পুনরাবৃত্তিতে ছোট পরিবর্তন যাতে আপনি উদাহরণস্বরূপ কোনও ট্যাব নিয়ন্ত্রণের চাইল্ড ট্যাব নিয়ন্ত্রণটি খুঁজে পেতে পারেন।
public static DependencyObject FindInVisualTreeDown(DependencyObject obj, Type type)
{
if (obj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
if (child.GetType() == type)
{
return child;
}
DependencyObject childReturn = FindInVisualTreeDown(child, type);
if (childReturn != null)
{
return childReturn;
}
}
}
return null;
}
জেনেরিক্স সিনট্যাক্স সহ এখানে আরও একটি কমপ্যাক্ট সংস্করণ রয়েছে:
public static IEnumerable<T> FindLogicalChildren<T>(DependencyObject obj) where T : DependencyObject
{
if (obj != null) {
if (obj is T)
yield return obj as T;
foreach (DependencyObject child in LogicalTreeHelper.GetChildren(obj).OfType<DependencyObject>())
foreach (T c in FindLogicalChildren<T>(child))
yield return c;
}
}
এবং এটি এভাবে উপরের দিকে কাজ করে
private T FindParent<T>(DependencyObject item, Type StopAt) where T : class
{
if (item is T)
{
return item as T;
}
else
{
DependencyObject _parent = VisualTreeHelper.GetParent(item);
if (_parent == null)
{
return default(T);
}
else
{
Type _type = _parent.GetType();
if (StopAt != null)
{
if ((_type.IsSubclassOf(StopAt) == true) || (_type == StopAt))
{
return null;
}
}
if ((_type.IsSubclassOf(typeof(T)) == true) || (_type == typeof(T)))
{
return _parent as T;
}
else
{
return FindParent<T>(_parent, StopAt);
}
}
}
}
মনে রাখবেন যে ভিজুয়ালটিহেল্পার ব্যবহার করা কেবলমাত্র ভিজুয়াল বা ভিজ্যুয়াল 3 ডি থেকে প্রাপ্ত নিয়ন্ত্রণগুলিতে কাজ করে। আপনার যদি অন্যান্য উপাদানগুলিও পরিদর্শন করতে হয় (যেমন টেক্সটব্লক, ফ্লোডোকামেন্ট ইত্যাদি), ভিজ্যুয়াল ট্রিহেলপার ব্যবহার করে একটি ব্যতিক্রম ছুঁড়ে ফেলা হবে।
এখানে একটি বিকল্প রয়েছে যা প্রয়োজনে যৌক্তিক গাছের কাছে ফিরে যায়:
http://www.hardcodet.net/2009/06/finding-elements-in-wpf-tree-both-ways
আমি একটি মন্তব্য যুক্ত করতে চেয়েছিলাম তবে আমার কাছে 50 টিরও কম কম রয়েছে তাই আমি কেবল "উত্তর" দিতে পারি। আপনি যদি এক্সএএমএল "টেক্সটব্লক" অবজেক্টগুলি পুনরুদ্ধার করতে "ভিজ্যুয়ালটিহেল্পার" পদ্ধতিটি ব্যবহার করেন তবে এটি এক্সএএমএল "বাটন" অবজেক্টগুলিকেও দখল করবে aware আপনি যদি "টেক্সটব্লক" অবজেক্টটি টেক্সটব্লকটি পাঠ্য প্যারামিটারে লিখে পুনরায় আরম্ভ করেন তবে আপনি আর বাটন.সন্টেন্ট প্যারামিটার ব্যবহার করে বাটন পাঠ্য পরিবর্তন করতে পারবেন না। বোতামটি স্থায়ীভাবে টেক্সটব্লক থেকে লেখা লিখিত পাঠ্যটি প্রদর্শন করবে write পাঠ্য রচনার ক্রিয়া (এটি পুনরুদ্ধার করার সময় থেকে -
foreach (TextBlock tb in FindVisualChildren<TextBlock>(window))
{
// do something with tb here
tb.Text = ""; //this will overwrite Button.Content and render the
//Button.Content{set} permanently disabled.
}
এটির কাজ করার জন্য, আপনি একটি এক্সএএমএল "টেক্সটবক্স" ব্যবহার করে একটি এক্সএএমএএল বোতামের নকল করার জন্য পদ্ধতিগুলি (বা ইভেন্টস) যুক্ত করতে পারেন। এক্সএএমএল "টেক্সটবক্স" "টেক্সটব্লক" অনুসন্ধানের মাধ্যমে সংগ্রহ করা হয় না।
সি ++ / সিএলআই এর জন্য আমার সংস্করণ
template < class T, class U >
bool Isinst(U u)
{
return dynamic_cast< T >(u) != nullptr;
}
template <typename T>
T FindVisualChildByType(Windows::UI::Xaml::DependencyObject^ element, Platform::String^ name)
{
if (Isinst<T>(element) && dynamic_cast<Windows::UI::Xaml::FrameworkElement^>(element)->Name == name)
{
return dynamic_cast<T>(element);
}
int childcount = Windows::UI::Xaml::Media::VisualTreeHelper::GetChildrenCount(element);
for (int i = 0; i < childcount; ++i)
{
auto childElement = FindVisualChildByType<T>(Windows::UI::Xaml::Media::VisualTreeHelper::GetChild(element, i), name);
if (childElement != nullptr)
{
return childElement;
}
}
return nullptr;
};
কিছু কারণে, এখানে পোস্ট করা উত্তরগুলির কোনওই আমাকে আমার মেইন উইন্ডোতে প্রদত্ত নিয়ন্ত্রণে থাকা প্রদত্ত ধরণের সমস্ত নিয়ন্ত্রণ পেতে সহায়তা করে না। আমার পুনরুক্তি করার জন্য সমস্ত মেনু আইটেমগুলি একটি মেনুতে খুঁজে পাওয়া দরকার। এগুলি সকলেই মেনুতে প্রত্যক্ষ বংশধর ছিল না, সুতরাং আমি উপরের কোডটি ব্যবহার করে কেবলমাত্র তাদের প্রথম লিলেন সংগ্রহ করতে সক্ষম হয়েছি। এই এক্সটেনশন পদ্ধতিটি যে কেউ এখানে নীচে পুরোপুরি পড়া চালিয়ে যাবেন তাদের সমস্যার জন্য আমার সমাধান।
public static void FindVisualChildren<T>(this ICollection<T> children, DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
var brethren = LogicalTreeHelper.GetChildren(depObj);
var brethrenOfType = LogicalTreeHelper.GetChildren(depObj).OfType<T>();
foreach (var childOfType in brethrenOfType)
{
children.Add(childOfType);
}
foreach (var rawChild in brethren)
{
if (rawChild is DependencyObject)
{
var child = rawChild as DependencyObject;
FindVisualChildren<T>(children, child);
}
}
}
}
আশা করি এটা সাহায্য করবে.
গৃহীত উত্তর আবিষ্কৃত উপাদান বেশী বা কম ফেরৎ unordered , যতটা সম্ভব গভীর হিসাবে প্রথম সন্তান শাখা নিম্নলিখিত যখন পথ ধরে আবিষ্কৃত উপাদান ফলনশীল, backtracking এবং এখনো পার্স গাছের শাখা জন্য পদক্ষেপ পুনরাবৃত্তি সামনে দ্বারা।
যদি আপনার উত্থানের ক্রমে বংশধর উপাদানগুলির প্রয়োজন হয় , যেখানে প্রত্যক্ষ বাচ্চাদের প্রথমে উত্সাহ দেওয়া হবে, তারপরে তাদের বাচ্চারা এবং এই জাতীয় নীচের কাজটি করা হবে:
public static IEnumerable<T> GetVisualDescendants<T>(DependencyObject parent, bool applyTemplates = false)
where T : DependencyObject
{
if (parent == null || !(child is Visual || child is Visual3D))
yield break;
var descendants = new Queue<DependencyObject>();
descendants.Enqueue(parent);
while (descendants.Count > 0)
{
var currentDescendant = descendants.Dequeue();
if (applyTemplates)
(currentDescendant as FrameworkElement)?.ApplyTemplate();
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(currentDescendant); i++)
{
var child = VisualTreeHelper.GetChild(currentDescendant, i);
if (child is Visual || child is Visual3D)
descendants.Enqueue(child);
if (child is T foundObject)
yield return foundObject;
}
}
}
ফলস্বরূপ উপাদানগুলি সবচেয়ে নিকটে থেকে দূর পর্যন্ত অর্ডার করা হবে। এটি দরকারী হবে উদাহরণস্বরূপ যদি আপনি কোনও প্রকার এবং শর্তের নিকটতম শিশু উপাদানটির সন্ধান করছেন:
var foundElement = GetDescendants<StackPanel>(someElement)
.FirstOrDefault(o => o.SomeProperty == SomeState);
child
অনির্ধারিত.
ব্রাইস, সত্যিই দুর্দান্ত উত্তর।
ভিবি.এনইটি সংস্করণ:
Public Shared Iterator Function FindVisualChildren(Of T As DependencyObject)(depObj As DependencyObject) As IEnumerable(Of T)
If depObj IsNot Nothing Then
For i As Integer = 0 To VisualTreeHelper.GetChildrenCount(depObj) - 1
Dim child As DependencyObject = VisualTreeHelper.GetChild(depObj, i)
If child IsNot Nothing AndAlso TypeOf child Is T Then
Yield DirectCast(child, T)
End If
For Each childOfChild As T In FindVisualChildren(Of T)(child)
Yield childOfChild
Next
Next
End If
End Function
ব্যবহার (এটি একটি উইন্ডোতে সমস্ত পাঠ্যবক্সকে অক্ষম করে):
For Each tb As TextBox In FindVisualChildren(Of TextBox)(Me)
tb.IsEnabled = False
Next
ভিজ্যুয়াল ট্রি সাহায্যকারী ব্যতীত আমি এটি আরও সহজ পেয়েছি:
foreach (UIElement element in MainWindow.Children) {
if (element is TextBox) {
if ((element as TextBox).Text != "")
{
//Do something
}
}
};