使用 C# WPF 通过标签调用/搜索按钮

call / Search Button by their tags using C # WPF

我有一个有 25 个按钮的屏幕,我喜欢通过代码与按钮进行交互。例如,使用随机函数生成一个数字:

Random rdn = new Random ();
number = rdn.Next (0,25);

比方说结果是20,如何调用标签为20的按钮,然后改变他的背景颜色?

myButton(????).Background = Brushes.Red;

我知道我可以一一完成:

if (number == 1)
{
BTN_1.Background = Brushes.Red;
}
if (number == 2)
{
BTN_2.Background = Brushes.Red;
}

但这是不对的。我不知道我是否清楚。谢谢

有很多方法可以做到这一点:

第一种方式(使用可视化工具箱编辑器):

您通过从 Visual Studio 工具箱中拖动添加了 25 个按钮

button1, button2 ... button25

如果它们按顺序排序,您只需这样做:

int index = 1; //button1
foreach (Control c in GridOrCanvas.Children)
{
                if(c is Button && index==number){ ((Button)c).background = ...; break; }
                else index++; 
}

另一种方式(仍在使用 visual studio 工具箱):

在程序的开头,将按钮 属性 "Name" 分配给您想要的数字(仍然认为它们是按顺序排列的):

int ind = 1;
foreach(Control c in GridOrCanvas.Children)
{
                 if(c is Button) c.Name = "_" + ind++.ToString(); //_1
}

现在,您只需执行相同的操作,但比较字符串:

foreach (Control c in GridOrCanvas.Children)
{
                if(c is Button && c.Name == "_" + number) { ((Button)c).background = ...; break; // "_" + 20 = "_20" }
}

另一种方法,是通过数组将它们添加到代码中:

Button[] Buttons = new Button[25];
for(int i=0; i< Buttons.Length; i++)
{
GridOrCanvas.Children.Add(Buttons[i] = new Button() { Width = ..., Height = ..., Content = "...", ..., etc });
Canvas.SetTop(Buttons[i], top_location);
Canvas.SetLeft(Buttons[i], left_location);
}

您现在已经有了按数字排序的数组...Buttons[0] 是 button1...

if(number > -1 && number < 26);
Buttons[number-1].Background = ...; //Faster way

最后一个愚蠢的方法,如果你的按钮有这个:

Button1.Content = "Button1";

你这样查就可以了:

foreach (Control c in GridOrCanvas.Children)
{
                if(c is Button) if(((Button)c).Content == "Button" + number)
                 { ((Button)c).background = ...; break; // "Button" + 20 = "Button20" }
}

通过使用标签,您只需将标签指定为姓名:

//假设你已经分配了标签: //button1.Tag = 1;

foreach(Control c in GridOrCanvas.Children)
{
         if(c is Button) if((int)(((Button)c).Tag) == number) { ((Button)c).background = ...; break; }
}

当您创建按钮时,像这样在标签 属性 中分配一个数字

 Button b1 = new Button();
 b1.Tag =1

等等..

您的按钮位于某种面板中。

foreach (var item in myPanel.Children)
            {
                if (item is Button)
                {
                    var button = (Button)item;
                    var buttonId = (int)button.Tag;
                    if (buttonId == number)
                    {
                        button.Background = Brushes.Red
                    }

                }
            }

您可以使用以下函数根据控件的任何属性值查找任何类型的控件。它将 return 具有相同值的控件列表。

public class ChildControls
{

        static public List<PropertyInfo> getPropertiesInfo(object myobject, bool considerReadWriteAttributes, bool canRead = true, bool canWrite = true)
        {
            List<PropertyInfo> objectPropertiesInfo;
            var myType = object.GetType();

            if(considerReadWriteAttributes)
                objectPropertiesInfo = myType.GetProperties().Where(p => (p.CanRead == canRead) && (p.CanWrite == canWrite) && p.GetCustomAttributes(typeof(System.ComponentModel.DataAnnotations.Schema.NotMappedAttribute), true).Length == 0).ToList();
            else
                objectPropertiesInfo = myType.GetProperties().Where(p => p.GetCustomAttributes(typeof(System.ComponentModel.DataAnnotations.Schema.NotMappedAttribute), true).Length == 0).ToList();

            return objectPropertiesInfo;
        }


        static public List<T> GetLogicalChildrenByProperty<T>(DependencyObject p_vParent, string propertyName, object propertyValue)
        {
            //create empty list of items of type T control
            List<T> childControlsList = new List<T>();
            List<object> childControls;

            //Get all child controls of a parent 
            childControls = LogicalTreeHelper.GetChildren(p_vParent).Cast<object>().ToList();

            //Loop through list of child controls and if child is required Type Control and its property value equal to givenValue then add to new list and set some of its properties            
            foreach (object obj in childControls)
            {
                if (obj.GetType() == typeof(T) || obj is T)
                {
                    bool shouldAdd = false;
                    T t = (T)obj;

                    if (propertyName != null && t != null)
                    {
                        var controlPropertiesInfo = Collections.getPropertiesInfo(obj, false, true, true);
                        var controlGivenPropertyInfo = controlPropertiesInfo.SingleOrDefault(d => d.Name == propertyName);

                        if (controlGivenPropertyInfo != null)
                        {
                            var controlGivenPropertyValue = controlGivenPropertyInfo.GetValue(obj);

                            if (controlGivenPropertyValue == popertyValue)
                                shouldAdd = true;
                        }
                    }

                    if (shouldAdd)
                        childControlsList.Add(t);
                }
            }

            return childControlsList;
        }
} 

它非常通用和动态。您可以按以下方式使用它。在您的情况下,它将始终 return 如您所说的一个按钮列表,每个按钮的标签 属性.

都有唯一的值
List<Button> myButtons = ChildControls.GetLogicalChildrenByProperty<Button>(gdButtons, "Tag", "20");

请注意,在我的例子中,gdButtons 是一个 Grid 类型的控件(容器或父控件),其中包含许多按钮(子控件)。

希望对你有帮助。

干杯,