Načtení hodnoty objektu podle MemberPath   zodpovězená otázka

C#, WPF, Silverlight

V Silverlight (ale stejně to bude i ve WPF) řeším následující problém.

Ve stringu MemberPath mám zadanou cestu vlastností nějakého objektu (jedná se o string co se zadává do Path binding výrazu nebo například do vlastnosti DisplayMemberPath ComboBoxu). Může tam být i více vlastností než jedna například tedy "Osoba.PracovniKalendar.Nazev".

Potřebuju kódem načíst hodnotu podle toho MemberPath z konkrétní instance objektu.

Nyní to řeším následujícím kódem přes pomocný control ContentPresenter a binding na vlastnost Content:

private static object GetItemValue(object item, string memberPath)
{
    var contentPresenter = new ContentPresenter();
    var binding = new System.Windows.Data.Binding(memberPath) { Source = item };
    contentPresenter.SetBinding(ContentPresenter.ContentProperty, binding);
    return contentPresenter.Content;
}

Tento kód se mi ale moc nelíbí, protože to vytváření controlu mi přijde trochu jako "prasárna".

Neví někdo o nějaké lepší řešení jak načíst požadovanou hodnotu.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Je možné ten objekt vložit do nějaké vlastnosti například ViewModelu, který je vložen v DataContextu?

Je možné ten objekt vložit jako dynamic resource?

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Kód je součástí controlu, který je poděděný z ComboBoxu a chová se jinak k jeho položkám.

Ten objekt ze kterého potřebuju načíst tu hodnotu je datový objekt z ItemsSource.

Volam to tam nějak takhle:

var sb = new System.Text.StringBuilder();
foreach (var item in this.ItemsSource)
{
    bool isSelected = Convert.ToBoolean(GetItemValue(item, this.SelectedValuePath));
    if (isSelected)
    {
        if (sb.Length > 0)
        {
            sb.Append(", ");
        }

        sb.Append(GetItemValue(item, this.DisplayMemberPath).ToString());
    }
}

Takže ViewModel ani resource asi nepomůže.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Než bych našel funkci, která to umí, tak bych si to asi napsal sám.

path.Split('.').Aggregate(obj, (acc, propName) => acc.GetType().GetProperty(propName).GetValue(obj))

Ale jestli máš v projektu assembly System.Web, tak DataBinder.Eval by tohle umět měl. Anebo holt reflectorem mrknout, kde WPF ty bindingy parsuje - podle mě to bude sice internal, ale přes reflexi to zavolat půjde.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Díky

Přes Reflektor jsem se koukal, ale tam je to moc zakutaný v ňákých IServiceProvider a IProvideValueTarget, a vedlo by to na hromady balastu okolo, kterej nepotřebuju.

Udělat to ručně mě nenapadlo, řešení s Aggregate zdá se chodí dobře a dostačuje.

nahlásit spamnahlásit spam 0 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:  
Heslo:  

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback