Eu tenho um botão dentro de um ControlTemplate. Como faço para obter uma referência a ele?
-
06-07-2019 - |
Pergunta
Eu só quero ativar ou desativar o botão dentro de um ControlTemplate para um Editor de WPF que eu estou usando.
Solução
Eu concordo com Joel que o método preferido seria para acionar a definição de propriedade Enabled do botão com marcação XAML, seja através de um gatilho ou ligando o valor activado para outra propriedade de dependência, possivelmente em um elemento pai, provavelmente com o ajuda de um ValueConverter.
No entanto, se você tem que fazê-lo explicitamente no C #, você pode usar o método FindName () na propriedade de modelo do botão. Há um MSDN 'como' ligados aqui .
Outras dicas
O meu eu recomendo que os botões são facilmente controlado através RoutedUICommands - incluindo ativação e desativação-los facilmente. Comandos não precisa de nenhum tipo de referência ao botão de modo Isto resolve o seu problema, também.
Veja aqui:
<Window.CommandBindings>
<CommandBinding
Command="{x:Static local:MyCommands.MyCommand}"
Executed="CommandBinding_Executed"
CanExecute="CommandBinding_CanExecute" />
</Window.CommandBindings>
<Window.Resources>
<ControlTemplate x:Key="MyTemplate" TargetType="Label">
<Button Command="{x:Static local:MyCommands.MyCommand}">
<TextBlock>
Click Me
<TextBlock Text="{TemplateBinding Content}" />
</TextBlock>
</Button>
</ControlTemplate>
</Window.Resources>
<StackPanel>
<Label Template="{StaticResource MyTemplate}">1</Label>
<Label Template="{StaticResource MyTemplate}">2</Label>
<Label Template="{StaticResource MyTemplate}">3</Label>
<Label Template="{StaticResource MyTemplate}">4</Label>
<Label Template="{StaticResource MyTemplate}">5</Label>
</StackPanel>
Use esta:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void CommandBinding_CanExecute(object sender, System.Windows.Input.CanExecuteRoutedEventArgs e)
{
// your logic here
int _Integer = -1;
int.TryParse(e.Parameter.ToString(), out _Integer);
e.CanExecute = _Integer % 2 == 0;
}
private void CommandBinding_Executed(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)
{
// do something when clicked
}
}
public static class MyCommands
{
public static RoutedUICommand MyCommand = new RoutedUICommand();
}
aparência:
Você realmente não deveria estar fazendo isso explicitamente, mas em vez disso ser defini-lo com Triggers no próprio ControlTemplate
. Esses gatilhos seriam reagindo a alguma outra mudança, e que defina a propriedade Enabled
do Button
.
Eu tive um problema com botões em ControlTemplates & DataTemplates. Acho gatilhos são muitas vezes demasiado pesado para fornecer exatamente o que meus clientes querem, eu acabei com muitos conversores. O método que eu tentei primeiro foi definir esses modelos mais difíceis em linha para que eles pudessem ser ligado a comandos (& eventos CodeBehind) em minhas telas ViewModel.
Se você está templates seu próprio controle, devo mencionar o método mais fácil é simplesmente o nome do botão, em seguida, usar algo como isto:
hourHand = this.Template.FindName( "PART_HourHand", this ) as Rectangle;
Recentemente, no entanto, eu mudei tato (de volta para arquivos indevidual .. RE-USE!), Mas começou a adição de um ViewModel (do tipo) que eu sufixo ...TemplateCommandStore
a todos os meus modelos que ficam um pouco complexa. Eu até usar isso quando templates meus CustomControls (para a consistência, principalmente)
public class BookingDetailsTemplateCommandStore
{
public OpenWindowCommand_Command OpenWindowCommand_Command { get; set; }
public BookingDetailsTemplateCommandStore()
{
OpenWindowCommand_Command = new OpenWindowCommand_Command( this );
}
}
Posso, então, felizmente usar este comando em um modelo. Você também pode passar referências de controle para o armazenamento de comando através da ligação a (dependência?) Propriedade para que a eventos de captura e controle de consumo mais preciso sobre seus modelos.
<DataTemplate DataType="{x:Type LeisureServices:BookingSummary}">
<Border Height="50" otherStyling="xyz">
<Border.Resources>
<local:BookingDetailsTemplateCommandStore x:Key="CommandStore" />
</Border.Resources>
<DockPanel>
<Button otherStyling="xyz"
Command="{Binding Source={StaticResource CommandStore},
Path=OpenWindowCommand_Command}" />
MVVM: eu acho que, enquanto a lógica gráfica é apenas isso, e completamente distinta da lógica de negócios, esta metodologia não interfere com MVVM. Em essência, eu adicionar C # código-capacidade consistente para Templates, que qualquer um que passou muito tempo em winforms pode perder tanto quanto eu.