2010-11-23 14 views
16

hay una manera de asignar un valor especial cuando un unión no se puede evaluar a causa de un valor nulo en el camino propiedad?utilizar un valor predeterminado cuando la unión no puede ser evaluada debido a un valor nulo

Por ejemplo si tengo una propiedad Nombre en una clase cliente y una unión como esta:

{Binding CurrentCustomer.Name} 

Cuando CurrentCustomer es nulo Me gustaría la unión para producir la cadena " --- ".

"TargetNullValue" y "FallbackValue" no parecen hacer el truco.

Gracias de antemano por su ayuda.

EDITAR:

De hecho lo que estoy tratando de hacer es sustituir un valor nueva fuente en lugar de la verdad cuando no está disponible. El escenario real es la siguiente:

un valor bool se utiliza para determinar la visibilidad de un control, pero cuando este valor no es alcanzable me gustaría reemplazarlo con "falsa".

Aquí es una ilustración que imita a la perfección mi caso de uso real:

MainPage.xaml.cs:

using System; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 

namespace TestSilverlightBindingDefaultValue 
{ 
    public class BoolToVisibilityConverter : IValueConverter 
    { 
     #region IValueConverter Members 

     public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
     { 
      return (bool)value ? Visibility.Visible : Visibility.Collapsed; 
     } 

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

     #endregion 
    } 

    public class Customer 
    { 
     public bool HasACar 
     { 
      get; 
      set; 
     } 
    } 

    public partial class MainPage : UserControl 
    { 
     public static readonly DependencyProperty CurrentCustomerProperty = 
      DependencyProperty.Register("CurrentCustomer", typeof(Customer), typeof(MainPage), null); 

     public Customer CurrentCustomer 
     { 
      get { return this.GetValue(CurrentCustomerProperty) as Customer; } 
      set { this.SetValue(CurrentCustomerProperty, value); } 
     } 

     public MainPage() 
     { 
      InitializeComponent(); 

      this.CurrentCustomer = null; 

      this.DataContext = this; 
     } 
    } 
} 

MainPage.xaml:

<UserControl x:Class="TestSilverlightBindingDefaultValue.MainPage" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:local="clr-namespace:TestSilverlightBindingDefaultValue" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
mc:Ignorable="d" 
d:DesignHeight="300" d:DesignWidth="400"> 
<UserControl.Resources> 
    <local:BoolToVisibilityConverter x:Key="boolToVisibilityConverter" /> 
</UserControl.Resources> 
    <StackPanel x:Name="LayoutRoot" Background="White"> 
    <TextBlock Text="You have a car" Visibility="{Binding CurrentCustomer.HasACar,Converter={StaticResource boolToVisibilityConverter}}" /> 
</StackPanel> 

FallbackValue no es la solución porque e solo cambiaría el valor generado y no el valor de origen.

Abe Heidebrecht ha proporcionado la solución perfecta para WPF con PriorityBinding pero no existe en Silverlight.

edición final: La segunda solución de Abe Heidebrecht, es decir, envoltura en otro elemento, está funcionando perfectamente.

Respuesta

20

Se puede usar un PriorityBinding:

<TextBlock> 
    <TextBlock.Text> 
     <PriorityBinding> 
      <Binding Path="CurrentCustomer.Name" /> 
      <Binding Source="---" /> 
     </PriorityBinding> 
    </TextBlock.Text> 
</TextBlock> 

bien, para Silverlight es un probablemente más fácil de utilizar con el elemento en una envoltura (como un borde).A continuación, tiene una IValueConverter para convertir nula a Visibility.Collapsed, y cualquier otra cosa que Visibility.Visible:

public class NullToVisibilityConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     return value != null ? Visibility.Visible : Visibility.Collapsed; 
    } 

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

y el uso que de este modo:

<Border Visibility="{Binding CurrentCustomer, Converter={StaticResource NullToVisibilityConverter}}"> 
    <TextBlock Text="You have a car" Visibility="{Binding CurrentCustomer.HasACar,Converter={StaticResource boolToVisibilityConverter}}" /> 
</Border> 
+0

No sabía que podría hacer esto ... Siempre he usado un DataTrigger comprobando si el valor es igual a '{x: Null}'. ¡Gracias! – Rachel

+0

Gracias, esta sería efectivamente la solución ... si no estuviera usando Silverlight 4 que no parece ser compatible con PriorityBinding. – Pragmateek

+1

He actualizado la respuesta para que refleje cómo hacerlo en Silverlight. –

13

Hey TargetNullValue y FallbackValue obras. Puede ser que la versión de .NET que está utilizando sea incorrecta.

Requiere .NET Framework 3.5 SP1 .TargetNullValue y FallbackValue es una nueva adición a la clase Binding

+0

Gracias, tienes razón, pero mi verdadero escenario es más complejo; Actualizaré mi pregunta inicial para dejarlo en claro. – Pragmateek

0

si utiliza NET Framework 3.5 o superior puede utilizar TargetNullValue En este ejemplo, si ha creado la propiedad de dependencia llamada BackgroundProperty puede usar targetNullvalue en la declaración de enlace. En este caso, paso el color de ResourcesDictionary.

<Style x:Key="LabelAxisNameStyle" TargetType="{x:Type Label}"> 
      <Setter Property="Background"> 
       <Setter.Value> 
        <Binding Path="BackgroundProperty" TargetNullValue="{StaticResource LabelTitleBrush}"/> 
       </Setter.Value> 
      </Setter> 
     </Style>    
Cuestiones relacionadas