Переключить (выбрать) оператор в Xaml Binding? - PullRequest
7 голосов
/ 06 декабря 2010

Есть ли способ создать условную привязку в XAML?

Пример:

<Window x:Name="Me" DataContext="{Binding ElementName=Me}">
    <TextBlock>
        <TextBlock.Text>
            <SelectBinding Binding="{Binding MyValue}">
                <Case Value="Value1" Value="value is 1!">                
                <Case Value="Value2" Value="value is 2!">                
                <Case Value="Value3" Value="value is 3!">                
            </SelectBinding >
        </TextBlock.Text>
    </TextBlock>
</Window>

В итоге, я хочу установить значение TextBlock в соответствии с другим значением Binding, которое может быть списком случаев, когда каждый случай (или случаи) адресован соответствующему выходу / установщику.

Может быть, я могу использовать DataTrigger в моем случае, я просто не знаю точно, как я это сделаю, так как я не использую здесь DataTemplate.

Обновление
В моем сценарии у меня есть UserControl, который имеет несколько элементов управления. Я хочу, чтобы в соответствии с определенным свойством в элементе данных UserControl.DataContext, другие элементы управления в пользовательском элементе управления были соответственно затронуты. В основном так же, как мой пример выше, только то, что каждый случай приводит к списку Setter s.

Ответы [ 4 ]

9 голосов
/ 06 декабря 2010

используйте DataTrigger

( EDITED - в оригинале допущена небольшая ошибка)

<TextBlock>
  <TextBlock.Style>
    <Style>
      <Style.Triggers>
        <DataTrigger Binding="{Binding MyValue}" Value="Value1">
          <Setter Property="TextBlock.Text" Value="value is 1!"/>
        </DataTrigger>
        <DataTrigger Binding="{Binding MyValue}" Value="Value2">
          <Setter Property="TextBlock.Text" Value="value is 2!"/>
        </DataTrigger>
        <DataTrigger Binding="{Binding MyValue}" Value="Value3">
          <Setter Property="TextBlock.Text" Value="value is 3!"/>
        </DataTrigger>
      </Style.Triggers>
    </Style>
  </TextBlock.Style>

6 голосов
/ 06 декабря 2010

У вас есть несколько вариантов ...

  • Вы можете использовать «DataTrigger», применив «Стиль» к своему текстовому блоку (используйте «Style.Triggers»).
  • Вы можете создать конвертер, который преобразует ваше «MyValue» в соответствующий текст.
  • Вы можете создать другое свойство для любого источника данных (в идеале это будет класс в стиле ViewModel), которое отражаеттекст, который должен отображаться.Обновите свойство из кода и привяжите непосредственно к нему, вместо того, чтобы помещать логику в XAML.

На самом деле я бы воспринял это как стилистический / дизайнерский выбор - ни один из вышеперечисленных не является по своей природе лучше или хужеони просто подходят для разных сценариев.

5 голосов
/ 06 декабря 2010

Попробуйте использовать Switch Converter, написанный Джошем:

SwitchConverter -

«Оператор переключения» для XAML - http://josheinstein.com/blog/index.php/2010/06/switchconverter-a-switch-statement-for-xaml/

Edit:

Вот код SwitchConverter, поскольку Сайт Джоша , кажется, не работает -

/// <summary>
/// A converter that accepts <see cref="SwitchConverterCase"/>s and converts them to the 
/// Then property of the case.
/// </summary>
[ContentProperty("Cases")]
public class SwitchConverter : IValueConverter
{
    // Converter instances.
    List<SwitchConverterCase> _cases;

    #region Public Properties.
    /// <summary>
    /// Gets or sets an array of <see cref="SwitchConverterCase"/>s that this converter can use to produde values from.
    /// </summary>
    public List<SwitchConverterCase> Cases { get { return _cases; } set { _cases = value; } }
    #endregion
    #region Construction.
    /// <summary>
    /// Initializes a new instance of the <see cref="SwitchConverter"/> class.
    /// </summary>
    public SwitchConverter()
    {
        // Create the cases array.
        _cases = new List<SwitchConverterCase>();
    }
    #endregion

    /// <summary>
    /// Converts a value.
    /// </summary>
    /// <param name="value">The value produced by the binding source.</param>
    /// <param name="targetType">The type of the binding target property.</param>
    /// <param name="parameter">The converter parameter to use.</param>
    /// <param name="culture">The culture to use in the converter.</param>
    /// <returns>
    /// A converted value. If the method returns null, the valid null value is used.
    /// </returns>
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        // This will be the results of the operation.
        object results = null;

        // I'm only willing to convert SwitchConverterCases in this converter and no nulls!
        if (value == null) throw new ArgumentNullException("value");

        // I need to find out if the case that matches this value actually exists in this converters cases collection.
        if (_cases != null && _cases.Count > 0)
            for (int i = 0; i < _cases.Count; i++)
            {
                // Get a reference to this case.
                SwitchConverterCase targetCase = _cases[i];

                // Check to see if the value is the cases When parameter.
                if (value == targetCase || value.ToString().ToUpper() == targetCase.When.ToString().ToUpper())
                {
                    // We've got what we want, the results can now be set to the Then property
                    // of the case we're on.
                    results = targetCase.Then;

                    // All done, get out of the loop.
                    break;
                }
            }

        // return the results.
        return results;
    }

    /// <summary>
    /// Converts a value.
    /// </summary>
    /// <param name="value">The value that is produced by the binding target.</param>
    /// <param name="targetType">The type to convert to.</param>
    /// <param name="parameter">The converter parameter to use.</param>
    /// <param name="culture">The culture to use in the converter.</param>
    /// <returns>
    /// A converted value. If the method returns null, the valid null value is used.
    /// </returns>
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

/// <summary>
/// Represents a case for a switch converter.
/// </summary>
[ContentProperty("Then")]
public class SwitchConverterCase
{
    // case instances.
    string _when;
    object _then;

    #region Public Properties.
    /// <summary>
    /// Gets or sets the condition of the case.
    /// </summary>
    public string When { get { return _when; } set { _when = value; } }
    /// <summary>
    /// Gets or sets the results of this case when run through a <see cref="SwitchConverter"/>
    /// </summary>
    public object Then { get { return _then; } set { _then = value; } }
    #endregion
    #region Construction.
    /// <summary>
    /// Switches the converter.
    /// </summary>
    public SwitchConverterCase()
    {
    }
    /// <summary>
    /// Initializes a new instance of the <see cref="SwitchConverterCase"/> class.
    /// </summary>
    /// <param name="when">The condition of the case.</param>
    /// <param name="then">The results of this case when run through a <see cref="SwitchConverter"/>.</param>
    public SwitchConverterCase(string when, object then)
    {
        // Hook up the instances.
        this._then = then;
        this._when = when;
    }
    #endregion

    /// <summary>
    /// Returns a <see cref="System.String"/> that represents this instance.
    /// </summary>
    /// <returns>
    /// A <see cref="System.String"/> that represents this instance.
    /// </returns>
    public override string ToString()
    {
        return string.Format("When={0}; Then={1}", When.ToString(), Then.ToString());
    }
}
0 голосов
/ 06 декабря 2010

Вы можете просто использовать конвертер, как предложил Дэн ...

public class MyValueConverter : IValueConverter
{
    public object Convert(
        object value, 
        Type targetType, 
        object parameter, 
        System.Globalization.CultureInfo culture)
    {
        string myValue = value.ToString();
        string output;

        switch(myValue)
        {
            case "Value1":
                output = "Value is 1";
                break;
            case "Value2":
                output = "Value is 2";
                break;
            case "Value3":
                output = "Value is 3";
                break;
            default:
                output = "Invalid Value";
                break;
        }

        return output;
    } 

    public object ConvertBack(
        object value, 
        Type targetType, 
        object parameter,
        System.Globalization.CultureInfo culture)
    {
        //Put reverse logic here
        throw new NotImplementedException();
    }
}

Затем вы можете использовать это изнутри вашего xaml ...

<TextBlock 
    Text="{Binding MyValue, Converter={StaticResource MyValueConverter}}"/>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...