|
|
Ligne 116 : |
Ligne 116 : |
| <ItemsControl ItemsSource="{Binding Source={StaticResource MyCollection}}" /> | | <ItemsControl ItemsSource="{Binding Source={StaticResource MyCollection}}" /> |
| </kode> | | </kode> |
| {{warn | Le Designer n’exécute pas le code-behind: le DataContext soit être définit dans le XAML.}} | | {{warn | Le Designer n’exécute pas le code-behind: le DataContext doit être définit dans le XAML.}} |
| * [[MVVM_Light_Toolkit#ViewModelLocator|ViewModelLocator]] | | * [[MVVM_Light_Toolkit#ViewModelLocator|ViewModelLocator]] |
|
| |
|
Version du 20 juillet 2020 à 16:04
Généralités
Permet la création d'interfaces graphiques. Remplace Windows Forms.
- Affichage vectoriel, cela permet d'augmenter la taille des objets en fonction de la résolution de l'écran sans effet de pixellisation.
- Séparation entre le code de l'interface graphique (XAML) et le code des fonctionnalités (C#).
WPF Version
|
Release
|
.NET Version
|
Visual Studio Version
|
Major Features
|
3.0 |
2006-11 |
3.0 |
|
Initial Release.
|
3.5 |
2007-11 |
3.5 |
VS 2008 |
Changes and improvements in: Application model, data binding, controls, documents, annotations, and 3-D UI elements.
|
3.5 SP1 |
2008-08 |
3.5 SP1 |
|
Native splash screen support, New WebBrowser control, DirectX pixel shader support. Faster startup time and improved performance for Bitmap effects.
|
4.0 |
2010-04 |
4.0 |
VS 2010 |
New controls: Calendar, DataGrid, and DatePicker. Multi-Touch and Manipulation
|
4.5 |
2012-08 |
4.5 |
VS 2012 |
New Ribbon control, New INotifyDataErrorInfo interface
|
4.5.1 |
2013-10 |
4.5.1 |
VS 2013 |
|
4.5.2 |
2014-05 |
4.5.2 |
|
|
4.6 |
2015-07 |
4.6 |
VS 2015 |
Transparent child window support HDPI and Touch improvements
|
Assemblages nécessaires
- PresentationCore
- PresentationFramework
- System.Xaml
- WindowsBase
Assemblages additionnels
Nom du paquet NuGet
|
Assemblages installés
|
Expression.Blend.Sdk.WPF |
- Microsoft.Expression.Interactions v4.5 (MouseDragElementBehavior, interactivity:DataTrigger)
- System.Windows.Interactivity v4.5 (Behavior, InvokeCommandAction, interactivity:EventTrigger)
|
System.Windows.Interactivity.WPF |
- Microsoft.Expression.Interactions v4.0
- System.Windows.Interactivity v4.0
|
Blend.Interactivity.WPF |
- Microsoft.Expression.Interactions v3.5
- System.Windows.Interactivity v3.5
|
Visual et Logical Tree
- Visual Tree: rendu final
- Logical Tree: code XAML
Permet d'afficher l'arborescence visuelle d'une fenêtre WPF.
Crtl + Shift → sélectionner un élément visuel
Récupérer les Templates des composants de base
|
// récupérer le template par défaut de button1 définit dans le XAML
using (var xw = new XmlTextWriter(@"ButtonDefaultTemplate.xml", null))
{
xw.Formatting = Formatting.Indented;
System.Windows.Markup.XamlWriter.Save(button1.Template, xw);
}
|
WPF Control Template Viewer
Forcer la culture locale dans WPF
Par défaut, WPF utilise la culture US English.
|
FrameworkElement.LanguageProperty.OverrideMetadata(
typeof(FrameworkElement), new FrameworkPropertyMetadata(
XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));
|
Erreurs
Impossible de créer le type inconnu ...
|
<MainControl xmlns:xxx="clr-namespace:Namespace">
<!-- Ajouter l'assembly car la définition du namespace n'est pas suffisante -->
<MainControl xmlns:xxx="clr-namespace:Namespace;assembly=Assembly">
|
Astuces
Icônes / Glyphes
NuGet → FontAwesome.WPF
|
<Window xmlns:fa="http://schemas.fontawesome.io/icons/">
<fa:ImageAwesome Icon="Refresh" Spin="True" Height="16" Width="16" />
|
Clipboard
|
Clipboard.SetText("Hello");
|
|
<!-- Définition d'un DataContext pour le design time et d'un autre pour le run time -->
<UserControl xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DataContext="{Binding ...}"
DataContext="{Binding ...}">
<UserControl.Resources>
<CollectionViewSource x:Key="MyCollection" Source="{Binding ...}" d:Source="{Binding ...}" />
</UserControl.Resources>
<ItemsControl ItemsSource="{Binding Source={StaticResource MyCollection}}" />
|
|
Le Designer n’exécute pas le code-behind: le DataContext doit être définit dans le XAML. |
Control à définir depuis le code-behind
|
<!-- Permet de définir le Control à afficher depuis le code-behind -->
<ContentControl Content="{Binding Path=AutreControl}"/>
|
UserControl internal
MyUserControl.xaml.cs
|
internal partial class MyUserControl : UserControl
{ }
|
MyUserControl.xaml
|
<UserControl x:Class="MyNamespace.MyUserControl"
x:ClassModifier="internal">
|
Un Enum dans du XAML
|
<MainControl xmlns:current="clr-namespace:CurrentNameSpace"
Propriete="{x:Static Member=current:MaClasse+MonEnum.Element1}">
|
|
namespace CurrentNameSpace
{
public class MaClasse
{
// public ou internal au minimum
internal enum MonEnum { Element1, Element2 }
}
}
|
|
<Image Source="C:\chemin\image.jpg" />
<!-- si la taille de l'image est réduite, utiliser DecodePixelWidth ou DecodePixelHeight
pour mettre en cache l'image réduite et non l'originale, ceci afin d'économiser de la mémoire -->
<Image Width="100">
<Image.Source>
<BitmapImage DecodePixelWidth="100" UriSource="C:\chemin\image.jpg" />
</Image.Source>
</Image>
<!-- ajouter l'image au projet:
Build action → Content
Copy to Output Directory → Copy if newer
L'image n'est pas embarqué dans l'assemblage -->
<Image Source="dossier/image.jpg" />
<!-- depuis un autre assemblage -->
<Image Source="/AssemblyName;component/dossier/image.jpg" />
|
|
Le format SVG n'est pas supporter nativement, il faut le convertir en XAML (avec Inkscape). |
Binding et web API
|
private ImageSource _imageBoxStream;
public ImageSource ImageBoxStream
{
get
{
return _imageBoxStream;
}
set
{
Set(() => ImageBoxStream, ref _imageBoxStream, value, true);
}
}
var request = new HttpRequestMessage(HttpMethod.Get, url);
var response = await _httpClient.SendAsync(request);
using (var stream = await response.Content.ReadAsStreamAsync())
{
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.StreamSource = stream;
bitmapImage.EndInit();
ImageBoxStream = bitmapImage;
}
|
|
<Image Source="{Binding ImageBoxStream}" Stretch="None" />
|
Image base64
|
var base64string = "data:image/jpeg;base64,XXXX";
var match = Regex.Match(response, @"data.+,(?<base64>.+)");
if (match.Success)
{
byte[] binaryData = Convert.FromBase64String(match.Groups["base64"].Value);
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.StreamSource = new MemoryStream(binaryData);
bitmapImage.EndInit();
ImageBoxStream = bitmapImage;
}
|
OriginalSource vs Source sur RoutedEventArgs
OriginalSource correspond à l'objet visuel alors que Source correspond à l'objet XAML.
|
<Button Content="Text"
PreviewMouseDown="Button_PreviewMouseDown"/>
|
|
private void Button_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
var source = e.Source; // Button
var originalSource = e.OriginalSource; // ButtonChrome
}
|
Arbre visuel correspondant :
- Button
- ButtonChrome
- ContentPresenter
- TextBlock
Rechercher tous les Control d'un type donné
|
public static IEnumerable<T> FindChildren<T>(this DependencyObject parent, Func<T, bool> predicate)
where T : DependencyObject
{
var children = new List<DependencyObject>();
if ((parent is Visual) || (parent is Visual3D))
{
var visualChildrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int childIndex = 0; childIndex < visualChildrenCount; childIndex++)
{
children.Add(VisualTreeHelper.GetChild(parent, childIndex));
}
}
foreach (var logicalChild in LogicalTreeHelper.GetChildren(parent).OfType<DependencyObject>())
{
if (!children.Contains(logicalChild))
{
children.Add(logicalChild);
}
}
foreach (var child in children)
{
var typedChild = child as T;
if ((typedChild != null) && predicate.Invoke(typedChild))
{
yield return typedChild;
}
foreach (var foundDescendant in FindChildren(child, predicate))
{
yield return foundDescendant;
}
}
yield break;
}
|
WPF vs UWP
WPF
- OS antérieur à Windows 10
- accès bas niveau au noyau et au matériel
- applications non-sanboxées, accès aux APIs système
- APIs graphique: radial brush, clipping mask
- Fenêtre transparente
- Accès plus fin à la bar de titre et au chrome des fenêtres
- intégration de WindowsForm
- chargement de code dynamique: plugins
- applications complexes à plusieurs fenêtres
UWP
- distribution via le store
- applications sanboxées
- code à destination de différents supports: smartphone, Xbox