Привязка разметки XAML к словарю с ключом типа Type - PullRequest
7 голосов
/ 21 февраля 2012

Я пытаюсь привязать к Dictionary<Type,string> через xaml.

Проблема в том, что индексатор [] в расширении разметки Binding интерпретирует его содержимое как строку.Есть ли какая-то «unescape-sequence» для этого случая?

<TextBox Text="{Binding theDictionary[{x:Type ns:OnePrettyType}]}" />

(Binding не работает, потому что {x:Type ns:OnePrettyType} отправляется как строка)

Ответы [ 2 ]

12 голосов
/ 21 февраля 2012

Если индексатор имеет определенный тип, преобразование должно выполняться автоматически, поэтому это должно работать:

{Binding theDictionary[ns:OnePrettyType]}

Если вам нужна явная интерпретация, вы можете попробовать «приведение» так:

{Binding theDictionary[(sys:Type)ns:OnePrettyType]}

(где sys отображается на пространство имен System, конечно)

Это была бы теория, но все это не сработает. Прежде всего, если вы используете конструктор Binding, который выбирает путь, приведение будет проигнорировано, так как он использует определенный конструктор PropertyPath определенным образом. Также вы получите ошибку привязки:

Ошибка System.Windows.Data: 40: Ошибка пути BindingExpression: свойство '[]' не найдено в 'object' '' Словаре`2 '

Вы должны будете заставить его создать PropertyPath через преобразователь типов, избегая конструктора Binding:

{Binding Path=theDictionary[(sys:Type)ns:OnePrettyType]}

Теперь это, скорее всего, просто вызовет исключение:

{"Параметр индексатора пути имеет значение, которое не может быть преобразовано в указанный тип: 'sys: Type'"}

Так что, к сожалению, преобразования типов по умолчанию не происходит. Затем вы могли бы создать PropertyPath в XAML и убедиться, что тип передан, но класс не предназначен для использования в XAML и выдает исключение, если вы попытаетесь, также очень неудачно.

Один из обходных путей - создать расширение разметки, которое выполняет построение, например,

[ContentProperty("Parameters")]
public class PathConstructor : MarkupExtension
{
    public string Path { get; set; }
    public IList Parameters { get; set; }

    public PathConstructor()
    {
        Parameters = new List<object>();
    }
    public PathConstructor(string path, object p0)
    {
        Path = path;
        Parameters = new[] { p0 };
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return new PropertyPath(Path, Parameters.Cast<object>().ToArray());
    }
}

Который затем можно использовать так:

<Binding>
    <Binding.Path>
        <me:PathConstructor Path="theDictionary[(0)]">
            <x:Type TypeName="ns:OnePrettyType" />
        </me:PathConstructor>
    </Binding.Path>
</Binding>

или как это

{Binding Path={me:PathConstructor theDictionary[(0)], {x:Type ns:OnePrettyType}}}
3 голосов
/ 21 февраля 2012

обновление: я оставляю это для справки по расширению Привязок

<Grid Width="{my:ParameterBinding {Binding [(0)],Source={x:Static my:SettingsService.Current}, Mode=TwoWay},{x:Type my:LeftPanelWidthSetting}}"/>

, и это код

[ContentProperty( "Parameters" )]
public class ParameterBinding : MarkupExtension
{
    public Binding Binding { get; set; }
    public IList Parameters { get; set; }

    public ParameterBinding()
    {
        Parameters = new List<object>(); 
    }

    public ParameterBinding( Binding b, object p0 )
    {
        Binding = b;
        Parameters = new []{p0};
    }

    public override object ProvideValue( IServiceProvider serviceProvider )
    {
        Binding.Path = new PropertyPath( Binding.Path.Path, Parameters.Cast<object>().ToArray() );
        return Binding.ProvideValue(serviceProvider);
    }
}

, который может быть расширен для поддержки болеепараметры во встроенном синтаксисе с дополнительными конструкторами.Я все еще оставляю возможность добавлять много параметров с расширенным синтаксисом элемента.

thx к HB для вдохновения этого

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...