2010-01-26 22 views
7

Llego al punto en una aplicación WPF donde todos los enlaces en mis controles son bastante repetitivos y también un poco demasiado detallados. Además, si quiero cambiar este enlace, tendría que cambiarlo en varios lugares en lugar de solo uno.¿Alguna forma de reutilizar enlaces en WPF?

¿Hay alguna forma de escribir la parte fuente del enlace una vez como en un recurso y luego reutilizarlo haciendo referencia a él con una sintaxis más compacta. He buscado esas capacidades pero no las he encontrado.

Lo que estoy haciendo ahora

<StackPanel> 
    <ToggleButton x:Name="someToggleButton" /> 
    <Button Visibility="{Binding ElementName=someToggleButton, Path=IsChecked, Converter={StaticResource BoolToVisibilityConverter}}" /> 
    <Grid Visibility="{Binding ElementName=someToggleButton, Path=IsChecked, Converter={StaticResource BoolToVisibilityConverter}}" /> 
    <TextBox Visibility="{Binding ElementName=someToggleButton, Path=IsChecked, Converter={StaticResource BoolToVisibilityConverter}}" /> 
    <CheckBox Visibility="{Binding ElementName=someToggleButton, Path=IsChecked, Converter={StaticResource BoolToVisibilityConverter}}" /> 
</StackPanel> 

Lo que yo quiero ser capaz de hacer (Pseudocódigo)

<StackPanel> 
    <StackPanel.Resources> 
     <Variable x:Name="someToggleButtonIsChecked" 
        Type="{x:Type Visibility}" 
        Value="{Binding ElementName=someToggleButton, Path=IsChecked, Converter={StaticResource BoolToVisibilityConverter}}" /> 
    </StackPanel.Resources> 

    <ToggleButton x:Name="someToggleButton" /> 
    <Button Visibility="{VariableBinding someToggleButtonIsChecked}" /> 
    <Grid Visibility="{VariableBinding someToggleButtonIsChecked}" /> 
    <TextBox Visibility="{VariableBinding someToggleButtonIsChecked}" /> 
    <CheckBox Visibility="{VariableBinding someToggleButtonIsChecked}" /> 
</StackPanel> 

¿Hay algún tipo similar de función o una técnica similar que me permitirá declarar la fuente de enlace una vez y luego volver a usarla?

+0

Generación de código ??? –

Respuesta

1

Puede vincular someToggleButton 's IsChecked a una propiedad en su viewmodel (el DataContext) y usar eso. Se vería algo como esto:

<StackPanel> 
<ToggleButton x:Name="someToggleButton" IsChecked="{Binding ToggleVisibility, Mode=TwoWay, Converter={StaticResource BoolToVisibilityConverter}}" /> 
<Button Visibility="{Binding ToggleVisibility}" /> 
<Grid Visibility="{Binding ToggleVisibility}" /> 
<TextBox Visibility="{Binding ToggleVisibility}" /> 
<CheckBox Visibility="{Binding ToggleVisibility}" /> 
</StackPanel> 

Esto requeriría que sus Window 's DataContext tiene una propiedad llamada ToggleVisibility de tipo Visibility.

EDIT:

Para eleborate más, el modelo de vista podría tener este aspecto:

public class SomeViewModel : INotifyPropertyChanged 
{ 

    private Visibility toggleVisibility; 

    public SomeViewModel() 
    { 
     this.toggleVisibility = Visibility.Visible; 
    } 

    public Visibility ToggleVisibility 
    { 
     get 
     { 
      return this.toggleVisibility; 
     } 
     set 
     { 
      this.toggleVisibility = value; 
      RaisePropertyChanged("ToggleVisibility"); 
     } 
    } 

    private void RaisePropertyChanged(string propertyName) 
    { 
     if (this.PropertyChanged != null) 
      this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 

    #region INotifyPropertyChanged Members 

    public event PropertyChangedEventHandler PropertyChanged; 

    #endregion 
} 

y que sería a continuación, establecer una instancia de ella como el DataContext en el Window o incluso sólo en el StackPanel

+0

Esto es en realidad similar a lo que tenía originalmente, pero era un poco código para agregar a mi código detrás para solo una propiedad. A la larga, si no hay soluciones basadas en XAML, probablemente regrese a hacerlo un poco más como MVVM. – jpierson

+0

@Jpierson Realmente debería volver a usar MVVM. Quiero decir que ya tienes un cuadro de texto, cuyo valor puedes vincular al modelo de vista, y un botón cuyo comando también puedes unir al modelo de vista. En mi opinión, viewmodels es el camino correcto, mientras que el código en windows no lo es. –

+0

Uso ViewModels actualmente en mi código principal, pero este código está en un pequeño cuadro de diálogo y agregando un ViewModel también me pareció innecesario ya que realmente no existía un "Modelo" para respaldar mi ViewModel. Otro problema que estoy teniendo al mismo tiempo es que tengo el caso donde necesito encadenar un BoolToVisibilityConverter y un InverseBoolConverter dentro de un enlace en un control. Al hacer una propiedad en mi código detrás o en ViewModel llamado específicamente IsNotDeleteMode, funcionaría pero luego tendré IsAddMode, IsNotAddMode, IsDeleteMode e IsNotDeleteMode propeties. Me parece un desastre, independientemente de a dónde vaya. – jpierson

0

¿Hay alguna forma de escribir la parte de origen del enlace una vez como en un fuente y luego reutilizarlo haciendo referencia a él con una sintaxis más compacta.

Quizás pueda hacer eso con PyBinding. No sé el alcance de sus capacidades, pero lo uso todo el tiempo para evitar convertidores de tipo. Aquí hay un ejemplo que uso mucho.

Visibility="{p:PyBinding BooleanToVisibility(IsNotNull($[.InstanceName]))}" 
  • BooleanToVisibility es una función que escribí en IronPython.
  • $ [. InstanceName] se une a la propiedad InstanceName del elemento vinculado a datos actual.

EDITAR: También puede usar esto para vincular la propiedad de una IU a la de otra. Aquí hay alguna información del archivo de ayuda.

  • $ [NameTextBlock.Texto] - La propiedad de texto del elemento con x: Name igual a "NameTextBlock"
  • $ [NameTextBlock] - Una instancia de TextBlock real, en lugar de una de sus propiedades
  • $ [{Auto}] - se unen a su yo. Equivalente a {Vinculante RelativeSource = {RelativeSource Self}}
  • $ [{Self} .Text] - La propiedad Text de usted mismo. Equivalente a {Binding Path = texto, RelativeSource = {RelativeSource Auto}}

http://pybinding.codeplex.com/

Teoría No comprobado

<StackPanel> 
    <ToggleButton x:Name="someToggleButton" /> 
    <Button Visibility="{p:PyBinding BooleanToVisibility($[someToggleButton.IsChecked])}" /> 
    <Grid Visibility="{p:PyBinding BooleanToVisibility($[someToggleButton.IsChecked])}"/> 
    <TextBox Visibility="{p:PyBinding BooleanToVisibility($[someToggleButton.IsChecked])}"/> 
    <CheckBox Visibility="{p:PyBinding BooleanToVisibility($[someToggleButton.IsChecked])}"/> 
</StackPanel> 

segundo intento

<StackPanel> 
    <ToggleButton x:Name="someToggleButton" /> 
    <Button Name="myButton" Visibility="{p:PyBinding BooleanToVisibility($[someToggleButton.IsChecked])}" /> 
    <Grid Visibility="{p:PyBinding $[myButton.Visibility]}"/> 
    <TextBox Visibility="{p:PyBinding $[myButton.Visibility]}"/> 
    <CheckBox Visibility="{p:PyBinding $[myButton.Visibility]}"/> 
</StackPanel> 
+0

Eso es bastante limpio, y algo que no sabía. El problema es que con ese enfoque es que realmente quiero almacenar el enlace en un solo lugar. Digamos, por ejemplo, que en algún momento quiero modificar la visibilidad de todos estos controles para que sean expulsados ​​de la propiedad ToggleButton.IsEnabled. Tendría que cambiarlo en varios lugares y es por eso que estoy interesado en declararlo una vez y luego volver a utilizarlo. – jpierson

+0

Puede nombrar su Botón y luego vincular la visibilidad de todos los demás controles. Sé que no es exactamente lo que quieres, pero está más cerca. –

+0

Sí, he hecho eso también. Llevándolo a otro nivel podría hacer un control personalizado genérico con una sola propiedad llamada algo así como Value (MyBindingControl ). Luego, para cada tipo que quiero reutilizar un enlace, podría hacer una clase especializada, como StringBindingControl: MyBindingControl . Esto podría usarse como una especie de variable a la que otros controles se podrían vincular. El principal problema de esta técnica es que es difícil de reutilizar en plantillas/estilos genéricos en los diccionarios de recursos, ya que lo más probable es que dependa de controles con nombre. – jpierson

0

Con sólo mirar el código original , puede agrupar los elementos necesarios en su propio contenedor y luego administrar el contenedor Visibilit Y:

<StackPanel> 
    <ToggleButton x:Name="someToggleButton" /> 
    <StackPanel Visibility="{Binding ElementName=someToggleButton, Path=IsChecked, Converter={StaticResource BoolToVisibilityConverter}}"> 
     <Button /> 
     <Grid /> 
     <TextBox /> 
     <CheckBox /> 
    </StackPanel> 
</StackPanel> 

En realidad, hoy me haría esto con la VSM - tener un estado con los elementos visibles y un estado con ellos no es visible, a continuación, utilizar dos comportamientos GoToState en el botón Cambiar para establecer el estado basado en el estado de alternancia del botón.

+1

Buen punto, sin embargo, este código fue creado para demostrar el deseo de reutilizar enlaces en general. Se podrían percibir casos en los que los elementos vinculados no se ubican claramente como pares dentro de un único contenedor. – jpierson

Cuestiones relacionadas