J'ai ceci en XAML
<ControlTemplate TargetType="{x:Type Button}">
<Image ...>
</ControlTemplate>
Je veux obtenir la même chose en code C #. Comment puis-je atteindre cet objectif?
ControlTemplate ct = new ControlTemplate();..
Image img = new Image();..
Maintenant, comment attribuer cette image au modèle de contrôle? Pouvons-nous faire cela ou manque-t-il un concept ici?
La création d'un modèle dans codebehind n'est pas une bonne idée, en théorie on pourrait le faire en définissant le ControlTemplate.VisualTree
qui est un FrameworkElementFactory
.
ControlTemplate template = new ControlTemplate(typeof(Button));
var image = new FrameworkElementFactory(typeof(Image));
template.VisualTree = image;
L'affectation de propriétés est très détournée car vous devez utiliser SetValue
et SetBinding
:
image.SetValue(Image.SourceProperty, ...);
Aussi, à propos de la réponse (précédemment) acceptée et des choses citées:
La définition du ControlTemplate par programmation est similaire à l'utilisation de XAML car nous devons utiliser la classe XamlReader.
Cette affirmation est juste fausse, nous ne le faisons pas "doit".
Si j'attribue des modèles au moment de l'exécution, je les définis comme une ressource que je peux charger si j'en ai besoin.
Edit: Selon la documentation FrameworkElementFactory
est déconseillé:
Cette classe est un moyen obsolète de créer par programme des modèles, qui sont des sous-classes de FrameworkTemplate telles que ControlTemplate ou DataTemplate; toutes les fonctionnalités du modèle ne sont pas disponibles lorsque vous créez un modèle à l'aide de cette classe. La méthode recommandée pour créer par programme un modèle consiste à charger XAML à partir d'une chaîne ou d'un flux de mémoire à l'aide de la méthode Load de la classe XamlReader.
Je me demande si cette recommandation est une si bonne idée. Personnellement, je continuerais à définir le modèle en tant que ressource en XAML si je peux éviter de le faire avec des chaînes et le XamlReader
.
La définition du ControlTemplate par programmation est similaire à l'utilisation de XAML car nous devons utiliser la classe XamlReader. Par exemple, voici le code pour définir le modèle d'un bouton, en supposant que nous voulons définir le modèle d'un bouton après son chargement.
private void Button_Loaded(object sender, RoutedEventArgs e) {
var button = sender as Button;
string template =
"<ControlTemplate xmlns='http://schemas.Microsoft.com/winfx/2006/xaml/presentation'
TargetType=\"Button\">" +
"<Border>" +
"<ContentPresenter/>" +
"</Border>" +
"</ControlTemplate>";
button.Template = (ControlTemplate)XamlReader.Parse(template);
}
Puisque nous avons utilisé une chaîne pour spécifier le code XAML du modèle, nous pouvons utiliser la méthode Parse de XamlReader. Le XamlReader possède également une méthode de chargement, qui est principalement utilisée pour les flux ou les lecteurs XAML ou XML. Notez que nous devons inclure l'espace de noms XML http://schemas.Microsoft.com/winfx/2006/xaml/presentation car le ControlTemplate, la bordure et les autres contrôles dont nous avons besoin y sont définis. Si nous ne l'avons pas inclus, nous rencontrerons une exception d'exécution. Fondamentalement, nous devons mettre les espaces de noms nécessaires au modèle.
Si vous devez uniquement changer l'image du bouton, vous pouvez faire une chose.
Maintenant, en XAML, utilisez-le dans le modèle de bouton
Sur la propriété Change of CurrentButtonImage mettre à jour l'image du bouton (dans le code derrière) en utilisant
CurrentImagePropertyChangedhandler(....,...)
{
switch(CurrentButtonImage)
{
case "Image1" :
this._ButtonImage.Fill = (DrawingBrush)csd.FindResource("Image1DrawingBrush");
break;
}
}