本文专用于记录WPF开发中的小细节,作为备忘录使用。
1. 关于绑定:
Text ="{Binding AnchorageValue,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
2. 关于ListBox的样式
//第一种
<ListBox.ItemContainerStyle> <Style TargetType="{x:Type ListBoxItem}"> <Style.Resources> <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" /> <SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black" /> </Style.Resources> <Setter Property="FocusVisualStyle" Value="{x:Null}"/> <Setter Property="HorizontalContentAlignment" Value="Stretch"/> </Style> </ListBox.ItemContainerStyle>
//第二种
<Style TargetType="ListBoxItem">
<Style.Resources>
<!--SelectedItem with focus-->
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="#C7C7C7" />
<!--SelectedItem without focus-->
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="#C7C7C7" />
</Style.Resources>
<!-- 设置触发器 -->
<Style.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Background" Value="#C7C7C7"/>
<Setter Property="Foreground" Value="Black"/>
</Trigger>
<Trigger Property="IsFocused" Value="true">
<Setter Property="Background" Value="#C7C7C7"/>
<Setter Property="Foreground" Value="Black"/>
</Trigger>
</Style.Triggers>
</Style>
3. DataGrid数据添加折叠
Resource:
<ResourceDictionary> <Style x:Key="GridGroupHeadStyle" TargetType="{x:Type GroupItem}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type GroupItem}"> <Expander x:Name="GroupExpander" IsExpanded="True" > <Expander.Header> <TextBlock Foreground="SlateBlue" FontSize="12"> <TextBlock.Text> <MultiBinding StringFormat="{}{0} ({1})"> <Binding Path="Name"/> <Binding Path="ItemCount"/> </MultiBinding> </TextBlock.Text> </TextBlock> </Expander.Header> <ItemsPresenter /> </Expander> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary>
//还有一种样式:
<ResourceDictionary>
<Style x:Key="GridGroupHeadStyle" TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander x:Name="GroupExpander" IsExpanded="True">
<Expander.Style>
<Style TargetType="{x:Type Expander}">
<Setter Property="Background" Value="CornflowerBlue"/>
</Style>
</Expander.Style>
<Expander.Header>
<TextBlock Foreground="Black" FontWeight="ExtraBold" FontSize="12" Text="{Binding Path=Name}"/>
</Expander.Header>
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Background" Value="Gainsboro"></Setter>
</Style>
</ResourceDictionary>
//还有一种样式:
<ResourceDictionary>
<Style x:Key="GridGroupHeadStyle" TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander x:Name="GroupExpander" IsExpanded="True" FlowDirection="RightToLeft">
<Expander.Style>
<Style TargetType="{x:Type Expander}">
<Setter Property="Background" Value="CornflowerBlue"/>
</Style>
</Expander.Style>
<Expander.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=Expander}, Path=DataContext.Name}"
Width="{Binding RelativeSource={RelativeSource AncestorType=Expander}, Path=ActualWidth}"
Margin="-30,0,0,0"
FlowDirection="LeftToRight">
</TextBlock>
</DataTemplate>
</Expander.HeaderTemplate>
<ItemsPresenter FlowDirection="LeftToRight"/>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Background" Value="Gainsboro"></Setter>
</Style>
</ResourceDictionary>
DataGrid: 需要注意的是DataGrid的ItemsSource绑定的是ViewModel中的Groups而不是Info
<DataGrid.GroupStyle> <GroupStyle ContainerStyle="{StaticResource GridGroupHeadStyle}"> <GroupStyle.Panel> <ItemsPanelTemplate> <DataGridRowsPresenter/> </ItemsPanelTemplate> </GroupStyle.Panel> </GroupStyle> </DataGrid.GroupStyle>
ViewModel: 这里的PropertyGroupDescription填写的是你分组所依据的字段,并且是存在于<Model>中的。
public ObservableCollection<Model> Info { get; set; } public ListCollectionView Groups { get; set; } Groups = new ListCollectionView(Info); Groups.GroupDescriptions.Add(new PropertyGroupDescription("Your Group Name"));
4. KeyboardNavigation.TabIndex
<TextBlock Grid.Row="0" Grid.Column="2" VerticalAlignment="Center" Height="16" Margin="0,17" KeyboardNavigation.TabIndex="4" > <Hyperlink x:Name="registerHyperlink" Click="Hyperlink_Click" KeyboardNavigation.TabIndex="5"> <Run Text="点此注册"/> </Hyperlink> </TextBlock>
5. Button设置IsDefault=“true”则可以按Enter键触发这个按钮
6. DataGrid有些列需要ToolTip,最好的方法是重新Template。不建议DataGrid.CellStyle全部统一加上ToolTip,因为值所在列内容较短根本不需要ToolTip。
<DataGridTemplateColumn Width="0.6*" Header="设置名称" > <DataGridTemplateColumn.CellTemplate> <DataTemplate> <TextBlock Text="{Binding Name}" ToolTip="{Binding Name}" FontSize="12" VerticalAlignment="Center"/> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn>
7. 假设一个DataGrid的一列全是button,建议不在Model中去实现button的功能,而是在ViewModel中统一用一个命令去完成,界面上必须这样做:
Command命令为UninstallCmd,写在ViewModel里
<UserControl.Resources> <ResourceDictionary> <DataTemplate x:Key="btnTemplate"> <Button Margin="5" Content="卸载" Command="{Binding Path=DataContext.UninstallCmd,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=DataGrid}}" CommandParameter="{Binding Isbn}" /> </DataTemplate> </ResourceDictionary> </UserControl.Resources> <DataGrid Name="dataGrid" Grid.Row="1" Margin="5,5" ItemsSource="{Binding Path=Isbns}" Background="White" AlternatingRowBackground="#EBEBEB" SelectionMode="Single" CanUserSortColumns="False" CanUserAddRows="False" AutoGenerateColumns="False" CanUserReorderColumns="False" CanUserResizeColumns="True" > <DataGrid.Columns> <DataGridTemplateColumn Header="是否卸载" Width="Auto" CellTemplate="{StaticResource btnTemplate}"/> </DataGrid.Columns> </DataGrid>
8. 在一些界面中使用PreviewMouseLeftButtonDown或者MouseLeftButtonDown会没有反应,这时候就只能使用PreviewMouseLeftButtonUp事件了。
<i:Interaction.Triggers> <i:EventTrigger EventName="PreviewMouseLeftButtonUp"> <i:InvokeCommandAction Command="{Binding ChangeDisplayCmd}"/> </i:EventTrigger> </i:Interaction.Triggers>
9. DataGrid的ColumnHeader需要绑定整个界面ViewModel的某一个属性,而不是DataGrid.ItemsSource中的值:
下面这个例子的DataGridTextColumn的Header绑定的就是界面ViewModel的ColorConfig属性。
<DataGridTextColumn Binding="{Binding SectionName}" IsReadOnly="True" Width="Auto" ElementStyle="{StaticResource standardCell}" MinWidth="120"> <DataGridTextColumn.HeaderTemplate> <DataTemplate> <TextBlock Text="{Binding DataContext.ColorConfig, RelativeSource={RelativeSource AncestorType=DataGrid}}" VerticalAlignment="Center"/> </DataTemplate> </DataGridTextColumn.HeaderTemplate> </DataGridTextColumn>
10. Image后台绑定时需要的是BitMapImage而不是简单的图片路径string,需要写Converter
//Xaml Code
<converters:MyConverter x:Key="MyImageConverter" FolderName="MyFolder"/> <Image Grid.Row="1" VerticalAlignment="Stretch" gif:ImageBehavior.AnimatedSource="{Binding MyImageSource, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged,Converter={StaticResource MyImageConverter}}"/>
//Converter Code
public class MyConverter : IValueConverter { public string FolderName { get; set; } public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value != null) { if (((string) value).Contains("SpecialText")) { return new BitmapImage(new Uri(value as string, UriKind.Absolute)); } else { string uriString = $"pack://application:,,,/{Assembly.GetExecutingAssembly().GetName()};component/Resources/Image/{FolderName}/{value}"; return new BitmapImage(new Uri(uriString)); } } return null; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return null; } }
11. Datagrid的水平及竖向网格都为虚线
<DataGrid.HorizontalGridLinesBrush> <LinearGradientBrush StartPoint="0,0" EndPoint="3,0" MappingMode="Absolute" SpreadMethod="Repeat"> <GradientStop Offset="0" Color="Black"/> <GradientStop Offset="0.5" Color="Black"/> <GradientStop Offset="0.5" Color="Transparent"/> <GradientStop Offset="1" Color="Transparent"/> </LinearGradientBrush> </DataGrid.HorizontalGridLinesBrush> <DataGrid.VerticalGridLinesBrush> <LinearGradientBrush StartPoint="0,0" EndPoint="0,3" MappingMode="Absolute" SpreadMethod="Repeat"> <GradientStop Offset="0" Color="Black"/> <GradientStop Offset="0.5" Color="Black"/> <GradientStop Offset="0.5" Color="Transparent"/> <GradientStop Offset="1" Color="Transparent"/> </LinearGradientBrush> </DataGrid.VerticalGridLinesBrush>
12. 当ListBox自定义Template时我们会发现,点选ListBox会出现两个选中项,但是我们已经设置了ListBox的SelectionMode为Single。我们需要对ListBox的Template中的控件做一些Style设置:
<TextBox Grid.Column="0" Width="73" Height="25" VerticalAlignment="Center" FontSize="12" Text="{Binding LowestHeight,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" TextChanged="LowHeight_TextChanged"> <TextBox.Style> <Style TargetType="{x:Type TextBox}"> <Setter Property="IsHitTestVisible" Value="False" /> <Style.Triggers> <DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}, AncestorLevel=1}}" Value="True"><Setter Property="IsHitTestVisible" Value="True" /> </DataTrigger> </Style.Triggers> </Style> </TextBox.Style>
13.Button的Style如何重写才能有效
<Style x:Key="BtnStyle" TargetType="{x:Type Button}"> <Setter Property="Control.Background" Value="Red"></Setter> <Setter Property="Control.Foreground" Value="White"></Setter> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type Button}"> <Grid Background="{TemplateBinding Background}"> <ContentPresenter x:Name="MyContentPresenter" Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center" /> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>