Има ли някакъв уникален идентификатор за wpf UIElement?

За регистриране на потребителски действия в моите WPF формуляри добавих някои глобални манипулатори на събития

Искам да регистрирам точно коя контрола задейства събитието, има ли някакъв уникален идентификатор за wpf UIElement като ClientId в ASP.Net?


person Arsen Mkrtchyan    schedule 03.04.2012    source източник
comment
Опитвали ли сте свойството FrameworkElement.Name ?   -  person DmitryG    schedule 03.04.2012
comment
Да, Дмитрий, но Името може да е празно, не искам да поставям Име на всяка контрола изключително за целите на регистриране   -  person Arsen Mkrtchyan    schedule 03.04.2012
comment
@ArsenMkrt, свойството PersistId изглежда бъди това, което търсиш. Уви, вече е остарял и очевидно няма заместител. Може би можете сами да се върнете към генерирането на уникални идентификатори, в такъв случай вижте този въпрос.   -  person Frédéric Hamidi    schedule 03.04.2012
comment
@FrédéricHamidi, със сигурност генерирането на id сам е добра идея, но в публикацията, която посочихте, идентификаторът ще бъде променен след рестартиране на приложението... което ще направи регистрационния файл неизползваем и не мисля, че има начин да генерирам стабилен идентификатор   -  person Arsen Mkrtchyan    schedule 03.04.2012
comment
Моето разбиране е, че начинът, по който XAML изгражда страница, не изисква уникален идентификатор за елемент на потребителския интерфейс. При липса на присвояване на уникален идентификатор не мисля, че ще намерите такъв. GetHashCode може да работи.   -  person paparazzo    schedule 03.04.2012


Отговори (7)


Защо не използвате хеш кода.

Можете да сравните стойностите, за да сте сигурни, че са един и същ обект, и е лесно да ги получите с .GetHashCode()


редактиране

Очевидно това е различно всеки път, когато стартирате програмата, така че всъщност това е лоша идея, освен ако не искате да актуализирате регистрационния файл всеки път, когато процесът се регистрира. Все пак е възможно

Искам да кажа, че можете да съхранявате хеш стойност за всеки обект по време на създаването на регистрационния файл, но не знам дали това ми харесва

person Jason Ridge    schedule 03.04.2012
comment
Тествах и проблемът е, че GetHashCode() е само за тази сесия. Ако затворите приложението и рестартирате, всички елементи на потребителския интерфейс ще получат нови хешкодове. Но все пак +1. - person paparazzo; 03.04.2012
comment
@ExitMusic, GetHashCode ще бъде променен поне след рестартиране на приложението, което ще направи дневника неизползваем... Искам да имам по-стабилен идентификатор - person Arsen Mkrtchyan; 03.04.2012

Изглежда намерих отговор на въпроса си, отговорът е Не, сега начин да го направя, Както е отбелязано в MSDN тук (http://msdn.microsoft.com/en-us/magazine/dd483216.aspx)

Забележете, че дефиницията на контрола на Window от най-високо ниво не съдържа атрибут Name. Това е важно, защото, както ще видим скоро, когато пишете тестова автоматизация, лесен начин да получите препратка към контрола, използвайки библиотеката MUIA, е да получите достъп до свойството AutomationId, което се генерира от компилатора от атрибута Name на контролата . Контролите без атрибут XAML Name няма да получат свойство AutomationId. Тази идея е конкретен пример от ниско ниво за важността на разглеждането на проблеми с дизайна на приложението за неща като сигурност, разширяемост и автоматизация на тестовете.

person Arsen Mkrtchyan    schedule 30.05.2012

Един от начините да направите това е с персонализиран атрибут. Така...

UIElement, който искате да регистрирате (UserControl например):

[UserInterfaceID(ID = "{F436E9B3-C2F6-4CF8-8C75-0A2A756F1C74}")]
public partial class MyUserControl : UserControl
{
    InitializeComponent();
    // or whatever...
}

След това се нуждаете от персонализирания клас атрибут

[System.AttributeUsage(AttributeTargets.Class)]
public class UserInterfaceIDAttribute : Attribute
{
    public Guid ID { get; set; }
}

Сега във вашия код можете да направите нещо подобно:

MyUserControl control = new MyUserControl();
foreach(object att in control.GetCustomAttributes(typeof(UserInterfaceAttribute),false))
{
    UserInterfaceAttribute uiAtt = (UserInterfaceAttribute)att;
    Guid theID = uiAtt.ID;
}

Тъй като маркирате контролата с атрибут в кода, уникалният идентификатор никога не се променя, без значение колко пъти убивате/стартирате приложението.

Разбира се, това е основен пример, който показва как да получите достъп до идентификатора, но вероятно ще искате да използвате някакъв вид аспектно ориентирано програмиране. Правя точно такива неща, използвайки Castle Windsor Interceptors, но това е извън обхвата на тази публикация.

В идеалния случай ще имате достъп до този идентификатор, когато има някакво събитие, което се задейства. Използването на прехващачи ви позволява да улавяте извиквания на метод, преди да бъдат извикани, където можете да потърсите идентификатора, както е показано по-горе, и да регистрирате действието. Като алтернатива можете просто да използвате

this.GetCustomAttributes(...)

в някакъв метод, когато се задейства събитие на контролата и вградете своя код за регистриране там. Този модел не е най-добрият, защото вие разпръсквате междусекторни опасения навсякъде, за да направите някакъв вид подход за аспектно ориентирано програмиране по-добър...но отново се отклонявам и това е извън обхвата на тази публикация...но получавате идея.

Надявам се това да помогне.

person Ricky    schedule 20.04.2012
comment
Защо имам нужда от атрибут? Мога да задам всички свойства на имената на моите UI елементи, просто искам да намеря начин, без да задавам нищо, защото е възможно в winform - person Arsen Mkrtchyan; 21.04.2012

Вие просто гледате да добавите Name или x:Name, така че Window/UserControl/Page да изложи контрола на останалата част от класа с посоченото име.

<Window ...>
   <Grid>
       ...

       <!-- These controls are named, so you can access them directly by name -->
       <Button x:Name="btnMyNamedButton" ... />
       <Button Name="btnMyOtherNamedButton" ... />

       <!-- This control is not named, so you can not directly access it by name -->
       <Button ... />
   <Grid>
</Window>

public partial class MyWindow : Window
{
    public MyWindow()
    {
        InitializeComponent();

        //btnMyNamedButton can be accessed
        //btnMyOtherNamedbutton can also be accessed

        //The third button can be accessed, but not directly by name.
    }
}

Освен това винаги можете да използвате FrameworkElement.Tag обект. Той е предназначен да съхранява произволна информация, така че можете да го използвате като уникален идентификатор, ако искате.

person myermian    schedule 03.04.2012
comment
благодаря за отговора @m-y, но името не е това, което търся, първо не искам да давам имена на всички контроли на потребителския интерфейс екскурзивно за регистриране, и второ, може да е невъзможно за мрежа с много контроли за редактиране в клетка шаблони... - person Arsen Mkrtchyan; 03.04.2012

Вярвам, че за регистриране на потребителски действия можете да използвате дървото на UIAutomation и свойството AutomationElement.AutomationId, тъй като този подход се поддържа във всички стандартни контроли на потребителския интерфейс по подразбиране. Много контроли на трети страни също поддържат AutomationId за своите елементи (напр. клетки на мрежата). AutomationId е полезен за създаване на скриптове за автоматизация на тестове.

person DmitryG    schedule 03.04.2012
comment
Хммм... изглежда AutomationId също трябва да бъде зададен и ако не е зададен, той връща име, което е празно в нашия случай... Предполагам, че няма начин да направя това, което търся... - person Arsen Mkrtchyan; 03.04.2012

вижте Свойство FrameworkElement.Tag

Свойството Tag може да се използва. Той е от тип object и може да бъде зададен на всичко.

person ergohack    schedule 25.09.2019

Мисля, че UIElement.Uid трябва да работи. Задайте го в XAML и достъп до него в код.

<Label Uid="FirstName"/>

ИЛИ в свойство стил

<Setter Property="Uid" Value="SecondName"/>

След това вижте в C# код:


    if (Keyboard.FocusedElement is UIElement uiElement)
    {
        Debug.WriteLine(this, $"{uiElement.Uid}");
    }

person nkanani    schedule 19.03.2021