為了得到更人性化的外觀,需要設計如何修剪資料串列和資料欄位,
資料轉換
在基本系結中,資訊從源到目標傳遞程序沒有任何變化,但有時候希望將資訊轉換到更友好的內容再呈現到界面上,WPF提供了兩個工具:
- 字串格式化
- 值轉換器
單個屬性
Binding.StringFormat 屬性針對簡單的,標準的格式化數字和日期而創建的,
<TextBox Text="{Binding Path=UnitCost, StringFormat={}{0:C}}"/>
<TextBox Text="{Binding Path=UnitCost, StringFormat=The value is {0:C}.}"/>
<ListBox DisplayMemberPath="UnitCost" ItemStringFormat="{0:C}"/>
值轉換器功能更強大,創建值轉換器需要4個步驟:
- 創建一個實作了 IValueConverter 介面的類
- 為該類宣告添加 ValueConversion 特性,并指定目標資料型別
- 實作 Convert() 方法
- 實作 ConvertBack() 方法
[ValueConversion(typeof(decimal), typeof(string))]
public class PriceConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
decimal price = (decimal)value;
return price.ToString("C", culture);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
string price = value.ToString(cultere);
decimal result;
if(Decimal.TryParse(price, NumberStyles.Any, cultere, out result))
return result;
return value;
}
}
<!--在Resources中創建轉換器物件,可以用于多個系結-->
<Window.Resources>
<local:PriceConverter x:Key="PriceConverter"/>
</Window.Resources>
<TextBox Text="{Binding Path=UnitCost, Converter={StaticResource PriceConverter}}"/>
多個屬性
<TextBlock>
<TextBlock.Text>
<!--使用 MultiBinding 替換 Binding-->
<MultiBinding StringFromat="{1}, {0}">
<Binding Path="FirstName"/>
<Binding Path="LastName"/>
</MultiBinding>
</TextBlcok.Text>
</TextBlock>
如果希望完成更復雜的作業,需要使用值轉換器:
<TextBox>
<TextBox.Text>
<MultiBinding Converter="{StaticResource ValueInStockConverter}">
<Binding Path="UnitCost"/>
<Binding Path="UnitsInStock"/>
</MultiBinding>
</TextBox.Text>
</TextBox>
public class VallueInStockConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
decimal unitCost = (decimal)values[0];
int unitsInStock = (int)value[1];
return unitCost * unitsInStock;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotSupportedException();
}
}
串列控制元件
ItemsControl 類為封裝串列中的控制元件定義了基本功能,所有串列控制元件都繼承自該類,
| 屬性名 | 說明 |
|---|---|
| ItemsSource | 資料源 |
| DisplayMemberPath | 期望資料項顯示的屬性 (更復雜的顯示使用ItemTemplate) |
| ItemStringFormat | 為每個項格式化文本 |
| ItemContainerStyle | 通過樣式可以設定封裝每個項的容器的多個屬性,自動創建這些封裝器物件 |
| ItemContainerStyleSelector | 為每項的封裝器選擇樣式的StyleSelector物件 |
| AIternationCount | 在資料中設定的交替集合數量 |
| ItemTemplate | 模板從系結的物件提取合適的資料并安排到合適的控制元件組合中 |
| ItemTemplateSelector | 為每個項選擇模板的 DataTemplateSelector 物件 |
| ItemsPanel | 用于包含串列中項的面板,所有封裝器都添加到這個容器中 |
| GroupStyle | 定義應當如何格式化每個分組 |
| GroupStyleSelector | 為每個分組選擇樣式的 StyleSelector 物件 |
串列樣式
ItemContainerStyle
當創建串列項時,串列控制元件會將其向下傳遞 ItemContainerStyle 屬性,每個串列項都將應用該樣式,
<ListBox Name="lstProducts" Margin="5" DisplayMemberPath="ModelName">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Background" Value="https://www.cnblogs.com/jqwang/archive/2022/01/18/LightSteelBlue"/>
<Setter Property="Margin" Value="https://www.cnblogs.com/jqwang/archive/2022/01/18/5"/>
<Setter Property="Padding" Value="https://www.cnblogs.com/jqwang/archive/2022/01/18/5"/>
<!--觸發器使得樣式更加精彩-->
<style.Triggers>
<Trigger Property="IsSelected" Value="https://www.cnblogs.com/jqwang/archive/2022/01/18/True">
<Setter Property="Background" Value="https://www.cnblogs.com/jqwang/archive/2022/01/18/DarkRed"/>
<Setter Property="Forground" Value="https://www.cnblogs.com/jqwang/archive/2022/01/18/White"/>
<Setter Property="BorderBrush" Value="https://www.cnblogs.com/jqwang/archive/2022/01/18/Blcak"/>
<Setter Property="BorderThickness" Value="https://www.cnblogs.com/jqwang/archive/2022/01/18/1"/>
</Trigger>
</Style.Triggers>
</Style>
<ListBox.ItemContainerStyle>
</ListBox>
可以讓每個 ListBoxItem 物件在項文本的旁邊顯示單選按鈕或復選框
<Window.Resources>
<Style x:Key="RadioButtonListStyle" TargetType="{x:Type ListBox}">
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="{x:Type ListBoxItem">
<Setter Property="Margin" Value="https://www.cnblogs.com/jqwang/archive/2022/01/18/2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<RadioButton Focusable="False" IsChecked="{Binding Path=IsSelected,Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}">
<!--ContentPresenter獲取最初在項中顯示的內容-->
<!--可能是文本,也可能是復雜的表示形式-->
<ContentPresenter/>
</RadioButton>
<!-- 多選框
<CheckBox Focusable="False" IsChecked="{Binding Path=IsSelected, Model=TwoWay,RelativeSource={RelativeSource TemplatedParent}}">
<ContentPresenter/>
</CheckBox>
-->
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
交替條目樣式
AlternationCount指定序列中項的數量,經過改數量后交替樣式,如果設定為2,第一個ListBoxItem的 AlternationIndex=0,第二個為1,第三個為0,第四個為1……,
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="https://www.cnblogs.com/jqwang/archive/2022/01/18/1">
<Setter Property="Background" Value="https://www.cnblogs.com/jqwang/archive/2022/01/18/LightBlue"/>
</Trigger>
</Style.Triggers>
資料模板
樣式提供了基本的格式化能力,但不管如何修改ListBoxItem,它都只是ListBoxItem.資料模板是一塊定義如何顯示系結的資料物件的XAML,有兩種型別的控制元件支持資料模板:
- 內容控制元件通過 ContentTemplate 屬性支持資料模板
- 串列控制元件通過 ItemTemplate 屬性支持資料模板
分離和重用模板
與樣式類似,通常也將模板宣告為視窗或程式的資源,
<Window.Resources>
<DataTemplate x:Key="ProductDataTemplate">
<Border Margin="5" BorderThickness="1" BorderBrush="StellBlue" CornerRadius="4"
Background="{Binding Path=Background, RelativeSource={
RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}}">
<Grid Margin="3">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RouDefinition>
<TextBlock FontWeight="Bold" Text="{Binding Path=ModelNumber}"/>
<TextBlock Grid.Row="1" Text="{Binding Path=ModelName}"/>
</Grid>
</Border>
</DataTemplate>
</Window.Resources>
通過 StaticResource 參考來為串列添加資料模板:
<ListBox Name="lstProducts" HorizontalContentAlignment="Stretch"
ItemTemplate="{StaticResource ProductDataTemplate}"/>
如果希望在不同型別的控制元件中自動重用相同的模板,可以通過設定 DataTemplate.DataType 屬性來確定使用模板的系結資料的型別,
<Window.Resources>
<!--模板將用于視窗中任何系結到Product物件的串列控制元件或內容控制元件-->
<DataTemplate DataType="{x:Type local:Product}">
...
</DataTemplate>
</Window.Resources>
改變模板
目前只能為整個串列使用一個模板,如果希望采用不同方式靈活展示不同的資料:
- 使用資料觸發器
- 使用值轉換器
- 使用模板選擇器
模板選擇器檢查系結物件并使用提供的邏輯選擇合適的模板,需要創建繼承自 DataTemplateSelector 的類,
ComboBox控制元件
與ListBox類不同的是,ComboBox類增加了另外兩個部分:顯示當前選擇項的選擇框和用于選擇項的下拉串列,
ComboBox提供了自動完成輸入功能,當鍵入內容時,WPF使用第一個匹配自動完成建議的項填充選擇框中的剩余內容,可以通過設定 ComboBox.IsTextSearchEnabled 屬性設定為 false 禁用該功能,
如果IsEditable屬性為 true,ComboBox控制元件不是顯示選擇項的副本,而是顯示選擇項的文本形式表示,WPF簡單呼叫ToString()方法,可以通過設定 TextSearch.TextPaht 附加屬性來定義選擇框顯示的內容:
<ComboBox IsEditable="True" IsReadOnly="True" TextSearch.TextPath="ModelName">
...
</ComboBox>
我的公眾號

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/415170.html
標籤:.NET技术
