WPF隨筆之 控件根據設定的顯示行數列數填充控件並自適應窗體大小(多綁定MVVM方式實現)

 

(效果圖,如見最下面)ide

需求:根據設置的行數列數,控制展現控件個數,而且填充的控件們大小剛恰好自適應填充滿固定的區域,而且調整窗體大小的時候控件動態自適應窗體大小,即自適應大小並不顯示滾動條(好比,設置了1行1列,則第一頁顯示一個控件,如設置了2行2列,則第一頁顯示第一行2個控件,第二行2個控件)。spa

解決方案,我總結有3code

1.在cs代碼裏面動態生成Grid控件,根據設定的行列動態生成行列,將控件自適應寬高填充進去orm

2.固定Grid。使用WrapPanel排序,當Grid實際寬高發生改變時,動態計算每個格子控件的寬高,經過綁定每個控件的寬高實現blog

3.使用MVVM方式,利用Converter實現排序

其實第一第二種都特別winform寫法,當年作MVC的時候,已經被MVC的模式洗腦,本身萬不得已的時候纔會使用這兩種方式去實現,因此不推薦你們使用get

當接手這個功能的時候已經有人使用方法2實現,在綁定的實體裏面加了三個屬性,FontSize、Width、Height,並且計算也不許確,忽略了margin,最小值設定等東西。(耦合性強,代碼錯亂,很差維護等缺點不一一列舉),如今改爲方式3去實現,特別簡單,咱們只須要使用Converter實現就好,由於ConverterParameter並不支持Binding寫法,這裏需用用到了多綁定方式去實現it

(代碼僅作參考,異常處理未寫)io

<ItemsControl Grid.Row="1"  x:Name="list" ItemsSource="{Binding DefectCodeInfoPage}"  >
                            <ItemsControl.ItemsPanel>
                                <ItemsPanelTemplate>
                                    <WrapPanel  IsItemsHost="True"/>
                                </ItemsPanelTemplate>
                            </ItemsControl.ItemsPanel>
                            <ItemsControl.ItemTemplate>
                                <DataTemplate>
                                    <!--高度應設最小值-->
                                    <Grid Margin="0 5 5 5" MinHeight="30">
                                        <Grid.Width>
                                            <MultiBinding Converter="{StaticResource WidthConverter}">
                                                <Binding ElementName="list" Path="ActualWidth" />
                                                <Binding Path="DataContext.Colunm" RelativeSource="{RelativeSource Mode=FindAncestor,AncestorType={x:Type local:ModPqcHeaderAdd}}"/>
                                                <Binding Path="Margin" RelativeSource="{RelativeSource Mode=Self}" />
                                            </MultiBinding>
                                        </Grid.Width>
                                        <Grid.Height>
                                            <MultiBinding Converter="{StaticResource HeightConverter}">
                                                <Binding ElementName="list" Path="ActualHeight" />
                                                <Binding Path="DataContext.Row" RelativeSource="{RelativeSource Mode=FindAncestor,AncestorType={x:Type local:ModPqcHeaderAdd}}"/>
                                                <Binding Path="Margin" RelativeSource="{RelativeSource Mode=Self}" />
                                            </MultiBinding>
                                        </Grid.Height>
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="7*" />
                                        <ColumnDefinition Width="3*" />
                                        </Grid.ColumnDefinitions>
                                        <Button
                                            Grid.Column="0"
                                            HorizontalAlignment="Stretch"
                                            VerticalAlignment="Stretch"
                                            Width="auto"
                                            Height="auto"
                                            Click="Button_MouseDown"
                                            Content="{Binding DEFECT_CODE_NAME, Mode=TwoWay}"
                                            FontFamily="Microsoft YaHei"
                                            FontSize="{Binding FontSize}"
                                            Foreground="Black"
                                            FontWeight="Bold"
                                            Tag="{Binding DEFECT_CODE, Mode=TwoWay}" />

                                        <TextBox
                                            Grid.Column="1"
                                            Width="auto"
                                            Height="auto"
                                            HorizontalAlignment="Stretch"
                                            VerticalAlignment="Stretch"
                                            HorizontalContentAlignment="Center"
                                            VerticalContentAlignment="Center"
                                            FontFamily="Microsoft YaHei"   
                                            FontSize="{Binding FontSize}"                                         
                                            Text="{Binding QTY, Mode=TwoWay}"
                                            TextAlignment="Center" />
                                    </Grid>
                                </DataTemplate>
                            </ItemsControl.ItemTemplate>
                        </ItemsControl>
部分代碼xaml

多綁定的Converter實現以下event

 1     [ValueConversion(typeof(double), typeof(double))]
 2     public class WidthConverter : IMultiValueConverter
 3     {
 4         public object Convert(object[] value, Type targetType, object parameter, CultureInfo culture)
 5         {
 6             double intWidth = 100;
 7             try
 8             {
 9 
10                 double actualWidth = (double)value[0];
11                 int cols = System.Convert.ToInt32(value[1]);
12                 Thickness margin = (Thickness)(value[2]);
13                 double lmargin = margin.Left;
14                 double rmargin = margin.Right;
15 
16                 if (cols == 0)
17                     return cols = 1;
18 
19                 intWidth = actualWidth / cols - cols * (lmargin + rmargin);
20             }
21             catch(Exception ex)
22             {
23             }
24             return intWidth;
25 
26         }
27         public object[] ConvertBack(object value, Type[] targetType, object parameter, CultureInfo culture)
28         {
29             return null;
30 
31         }
32 
33     }
34 
35     [ValueConversion(typeof(double), typeof(double))]
36     public class HeightConverter : IMultiValueConverter
37     {
38 
39         public object Convert(object[] value, Type targetType, object parameter, CultureInfo culture)
40         {
41             double intHeight = 30;
42             try
43             {
44 
45                 double actualHeight = (double)value[0];
46                 int rows = System.Convert.ToInt32(value[1]);
47                 Thickness margin = (Thickness)(value[2]);
48                 double tmargin = margin.Top;
49                 double bmargin = margin.Bottom;
50                 if (rows == 0)
51                     rows = 1;
52                 intHeight = actualHeight / rows - rows * (tmargin + bmargin);
53             }
54             catch
55             {
56             }
57             return intHeight;
58 
59         }
60         public object[] ConvertBack(object value, Type[] targetType, object parameter, CultureInfo culture)
61         {
62             return null;
63 
64         }
65 
66     }
Converters.cs

 

 噹噹噹當~~~~ 是否是超簡單,超簡潔的。這樣根本不用寫一堆屬性,還在各處去控制它們,總而言之一句話,「術業有專攻」,前臺的東西莫要帶走

 

 

設置一列一行時

設置兩行一列時

設置一行兩列時

設置N行N列時(忽略不截圖了)

相關文章
相關標籤/搜索