2016-06-04 2 views
2

У меня довольно стандартная настройка: на основании того, пусто ли содержимое TextBox, я хочу включить/отключить управление Button.Как связать элемент IsEnabled Button с содержимым TextBox?

Я пытался, что бы работал в приложении WPF, но это не дает желаемого поведения при работе на Windows, Runtime:

<StackPanel> 
    <TextBox x:Name="ItemNameTextBox" Header="Item" /> 
    <Button Content="Add Item" 
      IsEnabled="{Binding ElementName=ItemNameTextBox, 
           Path=Text.Length, 
           Mode=OneWay}" /> 
</StackPanel> 

во время выполнения, однако, это производит следующий вывод отладки 1):

Error: BindingExpression path error: 'Length' property not found on 'Windows.Foundation.IReference`1<String>'. 

сообщение об ошибке правильно: Windows::Foundation::IReference<String> Безразлично У вас есть Length.

Вопрос: Как связать IsEnabled свойство Button к TextBox свойству объекта длины текста? Должен ли я реализовывать пользовательский конвертер данных, или это можно сделать только с помощью разметки?


1) Полная выходная ошибка:

Error: BindingExpression path error: 'Length' property not found on 'Windows.Foundation.IReference`1<String>'. BindingExpression: Path='Text.Length' DataItem='Windows.UI.Xaml.Controls.TextBox'; target element is 'Windows.UI.Xaml.Controls.Button' (Name='null'); target property is 'IsEnabled' (type 'Boolean') 

ответ

2

Вы не можете связать логическое значение в целое число.

Вам необходимо создать конвертер, который возвращает логическое значение, значение которого истинно или ложно, в зависимости от значения целого. В вашем случае я предполагаю, что вы хотите, чтобы длина нуля возвращала false и длину больше нуля, чтобы вернуть значение true. Если в C++/cx Length не является свойством, а методом (в отличие от C#), вы не сможете напрямую привязываться к нему. Вы будете иметь, чтобы связать свойство Text, а затем вызвать метод Длина в конвертере:

public ref class LengthToIsEnabledConverter sealed : public Windows::UI::Xaml::Data::IValueConverter 
{ 
public: 
    virtual Platform::Object^ Convert(Platform::Object^ value, 
             Windows::UI::Xaml::Interop::TypeName targetType, 
             Platform::Object^ parameter, 
             Platform::String^ language) { 
     Platform::String^ text = safe_cast<Platform::String^>(value); 
     return (text->Length() > 0); 
    } 

    virtual Platform::Object^ ConvertBack(Platform::Object^ value, 
              Windows::UI::Xaml::Interop::TypeName targetType, 
              Platform::Object^ parameter, 
              Platform::String^ language) { 
     throw ref new Platform::NotImplementedException(); 
    } 
}; 

Затем в связывании добавить конвертер и изменить путь, чтобы быть просто текст:

IsEnabled="{Binding ElementName=ItemNameTextBox, 
        Path=Text, 
        Mode=OneWay, 
        Converter={StaticResource LengthToIsEnabledConverter}" /> 

где преобразователь объявлен в XAML как это:

<UserControl.Resources> 
    <converters:LengthToIsEnabledConverter x:Key="LengthToIsEnabledConverter " /> 
</UserControl.Resources> 
+0

это не совсем приста k out. Поскольку диагностика отладки говорит: * «Свойство« Длина »не найдено» *, поэтому его нельзя использовать. Вместо этого передавая свойство 'Text', и вычисление возвращаемого значения метода' Length() 'в преобразователе работает так, как ожидалось. Я не уверен, что все это необходимо. Действительно ли 'Platform :: String' действительно чужд привязке данных в Windows Runtime? – IInspectable

+0

@Inspectable - ах. Пропустил этот аспект. Я предположил, что именно отказ int -> bool вызывал это сообщение, а не обнаруживал его в первую очередь, но привязка к TextBox's Text является приемлемым решением. – ChrisF

+0

Это похоже на C#. Является ли тип 'string' проекцией для' Platform :: String' и обеспечивает ли это 'Length' как свойство (в отличие от функции-члена)? Я использую C++/CX, поэтому я не знаю. – IInspectable