【WPF】Wpf自定義控件及其數據自動刷新

之前四路溫度監控的時候有過這個想法,但是介於Winform用代碼添加控件的方法過於蛋疼所以最終採用了4線波形圖來實現。

但是在接觸wpf後,這個問題的兩個難點(控件設計麻煩和容器佈局麻煩)迎刃而解,於是便有了這個實驗

在項目中添加自定義控件

並在XAML中對其界面進行編輯

代碼如下:

        <StackPanel VerticalAlignment="Center">
            <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
                <TextBlock  Text="溫度計-" FontSize="30" HorizontalAlignment="Center"/>
                <TextBlock x:Name="txtName"  FontSize="30" HorizontalAlignment="Center"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
                <TextBlock  Text="溫度:" FontSize="25" HorizontalAlignment="Center"/>
                <TextBlock x:Name="txtTemp"  FontSize="25" HorizontalAlignment="Center"/>
            </StackPanel>
        </StackPanel>

擁有連個可設置屬性,一個是溫度計的編號,一個是溫度。同時在設計的時候應該限定其大小,否則可能會出現因爲內容大小變化出現自適應現象破壞觀感,這裏採用設置MaxHeight和MinHeight爲同一值來實現,寬度同理。

接下來編寫後臺代碼,實現數據的自動刷新

本空控件擁有兩組屬性,一組是溫度(私有),另一組是用於識別控件序號的的識別號(公有)

public int IDNo;
private double Temp;

控件初始化事件

初始化時默認溫度爲25℃,同時需要爲控件輸入一個編號

        public Moniter(int No)
        {
            InitializeComponent();
            txtName.Text = No.ToString();
            IDNo = No;
            Temp = 25;
            txtTemp.Text = "25℃";
        }

數據刷新事件,不採用反射模式(挺麻煩的)

        public void RefreshData(double data)
        {
            Temp += data;
            txtTemp.Text = Temp.ToString() + "℃";
        }

這樣一個溫度計自定義控件就設計完成了。

--------------------------------------------------------------------------分割線--------------------------------------------------------------------------------------

緊接着設計主界面,在主界面中我們需要一個容器來存放我們的控件,StackPanel、ListView和DataGrind都是可以的,但是由於我們設計的控件是圖像類控件且可能數量角度,在這裏採用ListView作爲容器存放控件,XAML代碼如下:

<StackPanel>
            <StackPanel Orientation="Horizontal">
                <Button x:Name="btnAddTemp" FontSize="25" Content="添加溫度計" Margin="2 2 2 2" Click="btnAddTemp_Click" />
                <TextBox x:Name="txtNo" Width="200">
                    <TextBox.Resources>
                        <VisualBrush x:Key="HintText" TileMode="None" Opacity="0.5" Stretch="None" AlignmentX="Left">
                            <VisualBrush.Visual>
                                <TextBlock FontStyle="Italic" Text="請輸入溫度計編號"/>
                            </VisualBrush.Visual>
                        </VisualBrush>
                    </TextBox.Resources>
                    <TextBox.Style>
                        <Style TargetType="TextBox">
                            <Style.Triggers>
                                <Trigger Property="Text" Value="{x:Null}">
                                    <Setter Property="Background" Value="{StaticResource HintText}"/>
                                </Trigger>
                                <Trigger Property="Text" Value="">
                                    <Setter Property="Background" Value="{StaticResource HintText}"/>
                                </Trigger>
                            </Style.Triggers>
                        </Style>
                    </TextBox.Style>
                </TextBox>
                <Button x:Name="btnChangeTemp" FontSize="25" Content="溫度+1" Margin="2 2 2 2" Click="btnChangeTemp_Click" />
            </StackPanel>
            <ListView x:Name="GoodsView" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Height="380"  ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
                <ListView.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapPanel IsItemsHost="True"/>
                    </ItemsPanelTemplate>
                </ListView.ItemsPanel>
            </ListView>
        </StackPanel>

效果如圖:

在這裏有兩個小細節

      其一是ListView的拉動和自適應設計(默認的ListView會將控件豎排拉伸並且無法向下滑動,明顯不符合我們的設計要求,所以對其ItemsPanel進行設置使其可以在空間允許的情況下橫向擺放控件;同時如果不設置長度的話容器將無法拖動,所以我們將其height屬性設置爲一個合適的值)

                <ListView.ItemsPanel>
                    <ItemsPanelTemplate>
                        <WrapPanel IsItemsHost="True"/>
                    </ItemsPanelTemplate>
                </ListView.ItemsPanel>

其次是用來選擇控件編號的輸入框,它有一組默認提示文字,實現方式如下

<TextBox x:Name="txtNo" Width="200">
                    <TextBox.Resources>
                        <VisualBrush x:Key="HintText" TileMode="None" Opacity="0.5" Stretch="None" AlignmentX="Left">
                            <VisualBrush.Visual>
                                <TextBlock FontStyle="Italic" Text="請輸入溫度計編號"/>
                            </VisualBrush.Visual>
                        </VisualBrush>
                    </TextBox.Resources>
                    <TextBox.Style>
                        <Style TargetType="TextBox">
                            <Style.Triggers>
                                <Trigger Property="Text" Value="{x:Null}">
                                    <Setter Property="Background" Value="{StaticResource HintText}"/>
                                </Trigger>
                                <Trigger Property="Text" Value="">
                                    <Setter Property="Background" Value="{StaticResource HintText}"/>
                                </Trigger>
                            </Style.Triggers>
                        </Style>
                    </TextBox.Style>
                </TextBox>

接着是後臺代碼:

按下添加按鈕會一次性添加10個溫度計控件到容器中

 for (int i = 1; i <= 10; i++)
            {
                GoodsView.Items.Add(new Moniter(i));
            }

而按下“溫度+1”則會根據選擇的溫度計將其溫度+1

foreach (Moniter item in GoodsView.ItemContainerGenerator.Items)
            {
                if (item.IDNo == Convert.ToInt32(txtNo.Text))
                {
                    item.RefreshData(1);
                }
            }

由於這種代碼添加的控件並不能對其name屬性進行預設,於是採用辨別ID號的方式來確定需要調用的控件。其原理是:先對容器內的所有控件進行遍歷,將其ID號與用戶選擇進行對比,然後調用其refreshdata方法刷新數據

將這段代碼插入到串口服務或者網絡服務中即可實現對所需控件的數據實時刷新的要求

最後,實現效果如下(添加商品是另一個實驗):

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章