WPF combina interfacce utente dell'applicazione, grafica 2D, grafica 3D, documenti e multimediali in un unico framework. Il suo motore di rendering vettoriale utilizza l'accelerazione hardware delle moderne schede grafiche. Questo rende l'interfaccia utente più veloce, scalabile e indipendenti dalla risoluzione.
L'illustrazione seguente fornisce una panoramica delle principali novità di WPF:
Separazione di aspetto e il comportamento WPF separa l'aspetto di un'interfaccia utente dal suo comportamento. L'aspetto è generalmente specificato nel Extensible Application Markup Language (XAML), il comportamento è implementato in un linguaggio di programmazione gestito come C # o Visual Basic. Le due parti sono legate insieme da associazione dati, eventi e comandi. La separazione di aspetto e il comportamento porta i seguenti benefici:
• Aspetto e comportamento sono debolmente accoppiati• I progettisti e gli sviluppatori possono lavorare su modelli separati.• strumenti di progettazione grafica in grado di lavorare su semplici documenti XML invece di codice di analisi.
Rich composizione
Controlli in WPF sono estremamente componibile. È possibile definire quasi tutti i tipi di controlli come contenuto di un altro. Questa flessibilità è una caratteristica molto potente se si utilizza in modo opportuno. Mettere un'immagine in un pulsante per creare un pulsante immagine, o mettere un elenco di video in un combobox per scegliere un file video.
<button>
<StackPanel Orientation="Horizontal">
<image Source="speaker.png" Stretch="Uniform"/>
<TextBlock Text="Play Sound" />
</ StackPanel></ Button>
Altamente personalizzabile A causa della netta separazione tra aspetto e il comportamento si può facilmente modificare l'aspetto di un controllo. Il concetto di stili permette di pelle controlli quasi come i CSS in HTML. I modelli consentono di sostituire tutto l'aspetto di un controllo.
L'esempio seguente mostra un pulsante predefinito WPF e un pulsante personalizzato.
Risoluzione indipendenza Tutte le misure in WPF sono unità logiche - non pixel. Una unità logica è un 1 / 96 di pollice. Se si aumenta la risoluzione dello schermo, l'interfaccia utente rimane delle stesse dimensioni - si arriva solo croccante. Dal momento che WPF si basa su un motore di rendering vettoriale basato è incredibilmente facile costruire interfacce utente scalabile.
lunedì 4 luglio 2011
lunedì 20 giugno 2011
ListBox con immagini
Il seguente esempio mostra come fare per inserire delle immagini in una listbox. La visualizzazione prevede gli items messi in orizzontale e per ogni item e' prevvista un'immagine e un testo alla base.
Per tale scopo viene creata una listbox facente riferimento ad una risorsa "listStyle" che definisce il template per l'item da visualizzare. Si noti che viene nascosta la barra verticale, mentre si utilizzarà solo quello orizzontale.
<ListBox
ItemContainerStyle="{StaticResource listStyle}"
ScrollViewer.VerticalScrollBarVisibility="Hidden">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
A questo punto nella sezione Resources della pagine e del controllo definiamo lo stile per l'item.
<Style TargetType="{x:Type ListBoxItem}" x:Key="listStyle">
<Setter Property="Template" Value="{StaticResource listControlTemplate}" ></Setter>
<Setter Property="Height" Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBox}}, Path=ActualHeight}" />
</Style>
In questo modo definiamo i SETTER e facciamo in modo che se la nostra listbox e' ridimensionabile in altezza, gli item verranno ridimensionati in modo da occupare tutta l'altezza e la larghezza verrà ridimensionata in modo proporzionale.
Definiamo quindi lo style listControlTemplate.
<ControlTemplate x:Key="listControlTemplate" TargetType="{x:Type ListBoxItem}" >
<Border x:Name="BorderImage" Margin="3,3,3,20" >
<Grid x:Name="listItemGrid" VerticalAlignment="Stretch" >
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="20" />
</Grid.RowDefinitions>
<Border BorderThickness="1" Background="Black" >
<Image x:Name="coverImage2" Tag="{Binding nPage}" Source="{Binding ., Converter={StaticResource ImageConverter} }" Stretch="Uniform" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Grid.Row="0" RenderTransformOrigin="1,1">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="1" ScaleY="1"/>
<SkewTransform AngleX="0" AngleY="0"/>
<RotateTransform Angle="0"/>
<TranslateTransform X="0" Y="0"/>
</TransformGroup>
</Image.RenderTransform>
</Image>
</Border>
<TextBlock Grid.Row="1" Text="{Binding nPage}" FontWeight="Bold"
HorizontalAlignment="Center" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding Path=sfondo}" Value="1">
<Setter Property="Background" Value="Aquamarine" TargetName="BorderImage"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding sfondo}" Value="10" >
<Setter Property="Background" Value="Black" TargetName="BorderImage"></Setter>
</DataTrigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="Blue" TargetName="BorderImage"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
Quindi definiamo che il binding dell'immagine avviene tramite ImageConvert.
<local:ImageConverter x:Key="ImageConverter" />
Questa e' una classe nella quale possiamo prendere le nostre immagini da file, da database o altro. Ovviamente l'informazione sarà nel campo (io normalmente uso delle classi in qui definisco i campi e poi per la lista dei dati uso una ObservableCollection che collego alla listbox.
La classe viene definita in questo modo :
#region "Converter Image"
public sealed class ImageConverter : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, CultureInfo culture)
{
try
{
BitmapSource btImage = null;
PageInfo pg = (PageInfo)value;
if (pg.IconPath != "")
{
BitmapImage ba = new BitmapImage(new Uri(pg.IconPath));
ba.BeginInit();
ba.CacheOption = BitmapCacheOption.OnLoad;
ba.EndInit();
btImage = ba;
}
else
{
btImage =new BitmapImage();
}
if (btImage.CanFreeze) btImage.Freeze();
return btImage;
}
catch
{
return new BitmapImage();
}
}
public object ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
#endregion
La classe PageInfo contiene i campi di cui faccio binding nella listbox; nel campo IconPath c'e' il path dell'immagine.
Ricordarsi di fare il Freeze dell'immagine altrimenti il GC non libererà mai la memoria anche nel caso si pulisca la listview.
Per tale scopo viene creata una listbox facente riferimento ad una risorsa "listStyle" che definisce il template per l'item da visualizzare. Si noti che viene nascosta la barra verticale, mentre si utilizzarà solo quello orizzontale.
<ListBox
ItemContainerStyle="{StaticResource listStyle}"
ScrollViewer.VerticalScrollBarVisibility="Hidden">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
A questo punto nella sezione Resources della pagine e del controllo definiamo lo stile per l'item.
<Style TargetType="{x:Type ListBoxItem}" x:Key="listStyle">
<Setter Property="Template" Value="{StaticResource listControlTemplate}" ></Setter>
<Setter Property="Height" Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBox}}, Path=ActualHeight}" />
</Style>
In questo modo definiamo i SETTER e facciamo in modo che se la nostra listbox e' ridimensionabile in altezza, gli item verranno ridimensionati in modo da occupare tutta l'altezza e la larghezza verrà ridimensionata in modo proporzionale.
Definiamo quindi lo style listControlTemplate.
<ControlTemplate x:Key="listControlTemplate" TargetType="{x:Type ListBoxItem}" >
<Border x:Name="BorderImage" Margin="3,3,3,20" >
<Grid x:Name="listItemGrid" VerticalAlignment="Stretch" >
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="20" />
</Grid.RowDefinitions>
<Border BorderThickness="1" Background="Black" >
<Image x:Name="coverImage2" Tag="{Binding nPage}" Source="{Binding ., Converter={StaticResource ImageConverter} }" Stretch="Uniform" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Grid.Row="0" RenderTransformOrigin="1,1">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="1" ScaleY="1"/>
<SkewTransform AngleX="0" AngleY="0"/>
<RotateTransform Angle="0"/>
<TranslateTransform X="0" Y="0"/>
</TransformGroup>
</Image.RenderTransform>
</Image>
</Border>
<TextBlock Grid.Row="1" Text="{Binding nPage}" FontWeight="Bold"
HorizontalAlignment="Center" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding Path=sfondo}" Value="1">
<Setter Property="Background" Value="Aquamarine" TargetName="BorderImage"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding sfondo}" Value="10" >
<Setter Property="Background" Value="Black" TargetName="BorderImage"></Setter>
</DataTrigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="Blue" TargetName="BorderImage"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
Quindi definiamo che il binding dell'immagine avviene tramite ImageConvert.
<local:ImageConverter x:Key="ImageConverter" />
Questa e' una classe nella quale possiamo prendere le nostre immagini da file, da database o altro. Ovviamente l'informazione sarà nel campo (io normalmente uso delle classi in qui definisco i campi e poi per la lista dei dati uso una ObservableCollection che collego alla listbox.
La classe viene definita in questo modo :
#region "Converter Image"
public sealed class ImageConverter : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, CultureInfo culture)
{
try
{
BitmapSource btImage = null;
PageInfo pg = (PageInfo)value;
if (pg.IconPath != "")
{
BitmapImage ba = new BitmapImage(new Uri(pg.IconPath));
ba.BeginInit();
ba.CacheOption = BitmapCacheOption.OnLoad;
ba.EndInit();
btImage = ba;
}
else
{
btImage =new BitmapImage();
}
if (btImage.CanFreeze) btImage.Freeze();
return btImage;
}
catch
{
return new BitmapImage();
}
}
public object ConvertBack(object value, Type targetType,
object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
#endregion
La classe PageInfo contiene i campi di cui faccio binding nella listbox; nel campo IconPath c'e' il path dell'immagine.
Ricordarsi di fare il Freeze dell'immagine altrimenti il GC non libererà mai la memoria anche nel caso si pulisca la listview.
martedì 3 maggio 2011
Selezionare il contenuto di una TextBox al Focus
Link originale: http://stackoverflow.com/questions/660554/how-to-automatically-select-all-text-on-focus-in-wpf-textbox.
La modifica consiste nell’includere il comportamento come un behavior. Ecco il codice:
E’ possibile ora aggiungere nello xaml il comportamento aggiungendo il behavior:
La modifica consiste nell’includere il comportamento come un behavior. Ecco il codice:
public static class TextBoxBehaviors { public static void SetSelectOnFocus(UIElement element, Boolean value) { element.SetValue(SelectOnFocusProperty, value); } public static bool GetSelectOnFocus(UIElement element) { return (bool)element.GetValue(SelectOnFocusProperty); } public static readonly DependencyProperty SelectOnFocusProperty = DependencyProperty.RegisterAttached("SelectOnFocus", typeof(bool), typeof(TextBoxBehaviors), new FrameworkPropertyMetadata(false, SelectOnFocusPropertyChangedCallback)); private static void SelectOnFocusPropertyChangedCallback(DependencyObject depObj, DependencyPropertyChangedEventArgs eventArgs) { TextBox tb = depObj as TextBox; if (tb != null) { if ((bool)eventArgs.OldValue == false && (bool)eventArgs.NewValue == true) { //attach events tb.PreviewMouseLeftButtonDown += SelectivelyIgnoreMouseButton; tb.GotKeyboardFocus += SelectAllText; tb.MouseDoubleClick += SelectAllText; } else if ((bool)eventArgs.OldValue == true && (bool)eventArgs.NewValue == false) { //detach events tb.PreviewMouseLeftButtonDown -= SelectivelyIgnoreMouseButton; tb.GotKeyboardFocus -= SelectAllText; tb.MouseDoubleClick -= SelectAllText; } } } private static void SelectivelyIgnoreMouseButton(object sender, MouseButtonEventArgs e) { DependencyObject parent = e.OriginalSource as UIElement; while (parent != null && !(parent is TextBox)) parent = VisualTreeHelper.GetParent(parent); if (parent != null) { var textBox = (TextBox)parent; if (!textBox.IsKeyboardFocusWithin) { textBox.Focus(); e.Handled = true; } } } private static void SelectAllText(object sender, RoutedEventArgs e) { var textBox = e.OriginalSource as TextBox; if (textBox != null) textBox.SelectAll(); } }
<TextBox Text="Selezionami per provare" behaviors:TextBoxBehaviors.SelectOnFocus="True" />
Etichette:
Codice,
Esempio,
TextBox,
Tips and Tricks
Iscriviti a:
Post (Atom)