controle para UIElements intercâmbio em WPF
-
19-08-2019 - |
Pergunta
O que é a maneira mais mínima para dinamicamente intercâmbio UIElement
s a uma certa "fenda" na interface do usuário? Eu tenho um número de UIElement
s e com base em alguma ligação de dados externo (por exemplo, uma seleção combobox) Pedir um deles para ser mostrado e o que era visível no momento para ser escondida. Assim, o comportamento é como o tipo de TabControl
mas sem a tabstrip, o cromo e as instâncias TabItem. Então, eu poderia realmente usar o TabControl
e substituir o modelo de controle. Mas isso é realmente a abordagem mais mínima?
Solução
Você tem várias opções. Como Bryan mencionado, modelo Seletores de dados pode definitivamente trabalho, embora Eu decidi que eles são muitas vezes um exagero. Leve o seu exemplo por exemplo - se você deseja vincular a visibilidade de um elemento para a seleção em um ComboBox
, eu preferiria um ValueConverter
. Passe o ComboBox.SelectedItem
ao Converter
e tê-lo retornar um valor Visibilidade:
public class MyObjectToVisibleOrCollapsed : IValueConverter
{
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is MyObject)
{
var myObject = (MyObject)value;
if (myObject.SomeState)
{
return Visibility.Visible;
}
}
return Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
Agora, em seus Window.Resources, crie uma instância da ValueConverter
e Bind o Elemento ao ComboBox.SelectedItem
usando a instância ValueConverter
:
<local:MyObjectToVisibleOrCollapsed x:Key="myObjectToVisibleOrCollapsed"/>
<DataTemplate x:Key="MyTemplate">
<TextBlock Text="{Binding Path=myText}"
x:Name="MyText"
Visibility="{Binding ElementName=MyComboBox, Path=SelectedItem, Converter={StaticResource myObjectToVisibleOrCollapsed}, Mode=Default}" />
</DataTemplate>
E, claro, você pode reutilizar o ValueConverter
para todos os elementos em seu DataTemplate
(e se há um monte deles, então a abordagem seletor de modelo de dados se torna mais desejável).
[Disclaimer: o código acima foi hash fora da memória e não testado - ele pode precisar de um pouco de ajustes]
Outras dicas
<ContentControl Content="{Binding SomePropertyThatYieldsTheContent}"/>
Eu não sei se esta é a forma mais sucinta, mas se você estiver usando um DataTemplate
, você poderia usar DataTrigger
s (a suposição aqui é que a visibilidade inicial é Collapsed
):
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=SourceProperty.ValueType}">
<DataTrigger.Value>
<pm:ValueType>Text</pm:ValueType>
</DataTrigger.Value>
<Setter TargetName="TextEditor" Property="Visibility" Value="Visible" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=SourceProperty.ValueType}">
<DataTrigger.Value>
<pm:ValueType>Logical</pm:ValueType>
</DataTrigger.Value>
<Setter TargetName="LogicalEditor" Property="Visibility" Value="Visible" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=SourceProperty.ValueType}">
<DataTrigger.Value>
<pm:ValueType>DateTime</pm:ValueType>
</DataTrigger.Value>
<Setter TargetName="DateEditor" Property="Visibility" Value="Visible" />
</DataTrigger>
...
Eu criar controles de usuário personalizadas para cada 'view' possível.
Sua visibilidade é alterado usando c #, tu. Pouco necessidade de programação.
A principal razão para esta abordagem é a facilidade de desenvolvimento -. O designer se concentra em particular, vista em vez do conjunto de todos os controles posible que vai estar lá
dados do modelo Seletores , Bea Stollnitz tem um bom post aqui . Basicamente, você vai usar um ContentPresenter
em cada uma de suas UI "slots" e, em seguida, use a propriedade ContentTemplateSelector
para definir quais seletor de modelo que você vai usar.
A maneira que eu faço é a camada dos elementos em cima uns dos outros e programaticamente alterar sua propriedade Visibilidade do visível ao colapso e volta conforme necessário.