WPF開發經驗-實現一種通用閥門控制項

来源:https://www.cnblogs.com/wwwen/archive/2022/12/19/16992344.html
-Advertisement-
Play Games

一 引入 在設計設備界面時,經常會有一種需求,展示一個閥門,閥門有通斷兩種狀態: 二 CommonValveControl 考慮實現一個自定義控制項,CommonValveControl。 使用自定義控制項比用戶控制項更靈活,更具擴展性,可以使用不同的樣式和模板。 CommonValveControl定義 ...


一 引入

在設計設備界面時,經常會有一種需求,展示一個閥門,閥門有通斷兩種狀態:

 

二 CommonValveControl

考慮實現一個自定義控制項,CommonValveControl。

使用自定義控制項比用戶控制項更靈活,更具擴展性,可以使用不同的樣式和模板。

CommonValveControl定義兩個依賴屬性,Orientation表示安裝展示的方向,Status表示閥門的通斷狀態。

public class CommonValveControl : Control
{
    static CommonValveControl()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(CommonValveControl), new FrameworkPropertyMetadata(typeof(CommonValveControl)));
    }
   
    public bool Status
    {
        get => (bool)GetValue(StatusProperty);
        set => SetValue(StatusProperty, value);
    }
    public static readonly DependencyProperty StatusProperty = DependencyProperty.Register(
       "Status",
       typeof(bool),
       typeof(CommonValveControl));
    
    public Orientation ValveOrientation
    {
        get => (Orientation)GetValue(CommonValveOrientationProperty);
        set => SetValue(CommonValveOrientationProperty, value);
    }
    public static readonly DependencyProperty CommonValveOrientationProperty = DependencyProperty.Register(
        "ValveOrientation",
        typeof(Orientation),
        typeof(CommonValveControl));
}

設計CommonValveControl的樣式模板,可通過設計不同的模板,以呈現出不同的效果。

通過ValveOrientation屬性觸發切換閥門的豎直狀態和水平狀態。

<Style TargetType="{x:Type local:CommonValveControl}">
    <Setter Property="Cursor" Value="Hand" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:CommonValveControl}">
                <Viewbox Stretch="Fill">
                    <Grid>
                        <Canvas Width="40" Height="40" >
                            <Ellipse Height="40" Width="40" Fill="Gray"/>
                            <Ellipse x:Name="InnerEllipse" Height="30" Width="30" Canvas.Left="5" Canvas.Top="5" 
                            <Rectangle x:Name="Rectangle" Fill="White" RadiusX="2" RadiusY="2"/>
                        </Canvas>
                    </Grid>
                </Viewbox>
                <ControlTemplate.Triggers>
                    <Trigger Property="Status" Value="false">
                        <Setter TargetName="InnerEllipse" Property="Fill" Value="Red"/>
                    </Trigger>
                    <Trigger Property="Status" Value="true">
                        <Setter TargetName="InnerEllipse" Property="Fill" Value="Green"/>
                    </Trigger>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="ValveOrientation" Value="Horizontal"/>
                            <Condition Property="Status" Value="false"/>
                        </MultiTrigger.Conditions>
                        <Setter TargetName="Rectangle" Property="Width" Value="6"/>
                        <Setter TargetName="Rectangle" Property="Height" Value="30"/>
                        <Setter TargetName="Rectangle" Property="Canvas.Left" Value="17"/>
                        <Setter TargetName="Rectangle" Property="Canvas.Top" Value="5"/>
                    </MultiTrigger>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="ValveOrientation" Value="Horizontal"/>
                            <Condition Property="Status" Value="true"/>
                        </MultiTrigger.Conditions>
                        <Setter TargetName="Rectangle" Property="Width" Value="30"/>
                        <Setter TargetName="Rectangle" Property="Height" Value="6"/>
                        <Setter TargetName="Rectangle" Property="Canvas.Left" Value="5"/>
                        <Setter TargetName="Rectangle" Property="Canvas.Top" Value="17"/>
                    </MultiTrigger>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="ValveOrientation" Value="Vertical"/>
                            <Condition Property="Status" Value="false"/>
                        </MultiTrigger.Conditions>
                        <Setter TargetName="Rectangle" Property="Width" Value="30"/>
                        <Setter TargetName="Rectangle" Property="Height" Value="6"/>
                        <Setter TargetName="Rectangle" Property="Canvas.Left" Value="5"/>
                        <Setter TargetName="Rectangle" Property="Canvas.Top" Value="17"/>
                    </MultiTrigger>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="ValveOrientation" Value="Vertical"/>
                            <Condition Property="Status" Value="true"/>
                        </MultiTrigger.Conditions>
                        <Setter TargetName="Rectangle" Property="Width" Value="6"/>
                        <Setter TargetName="Rectangle" Property="Height" Value="30"/>
                        <Setter TargetName="Rectangle" Property="Canvas.Left" Value="17"/>
                        <Setter TargetName="Rectangle" Property="Canvas.Top" Value="5"/>
                    </MultiTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

三 效果演示

Xaml代碼:

<Canvas>
    <local:PipeControl Width="106" Height="14" Canvas.Left="26" Canvas.Top="53"/>
    <local:PipeControl Width="14" Height="80" Canvas.Left="185" Canvas.Top="22" Orientation="Vertical"/>
    <local:CommonValveControl x:Name="valve1" Status="False" ValveOrientation="Horizontal" Width="40" Height="40" Canvas.Left="60" Canvas.Top="41"/>
    <local:CommonValveControl x:Name="valve2" Status="False" ValveOrientation="Vertical" Width="40" Height="40" Canvas.Left="172" Canvas.Top="41"/>
    <Button Content="Open" Click="OpenButton_Click" Canvas.Left="272" Canvas.Top="15" Width="66" Height="35"/>
    <Button Content="Close" Click="CloseButton_Click" Canvas.Left="272" Canvas.Top="71" Width="66" Height="35"/>
</Canvas>

 後臺代碼:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void OpenButton_Click(object sender, RoutedEventArgs e)
    {
        valve1.Status = true;
        valve2.Status = true;
    }

    private void CloseButton_Click(object sender, RoutedEventArgs e)
    {
        valve1.Status = false;
        valve2.Status = false;
    }
}

 

__ 以 上 __

一團靜火的頭像
  • 本文作者: 一團靜火
  • 本文鏈接: https://www.cnblogs.com/wwwen/p/16992344.html
  • 關於博主: 水平有限,不足或錯誤之處,請批評指正。如果文章對您有幫助,可以點擊文章右下角【推薦】一下。
  • 版權聲明: 本博客所有文章除特別聲明外,系原創文章,均採用 BY-NC-SA 許可協議。轉載請註明出處!並保留此段內容。

  • 您的分享是我們最大的動力!

    -Advertisement-
    Play Games
    更多相關文章
    • Shell 變數(一) bash shell 編程和其他編程語言差不多,同樣包含變數(存放字元串和數值的容器,可以進行修改、比較、傳遞)。在引用 bash 變數時,可以使用一些非常特殊的運算符。bash 還擁有內建變數,這些變數可以提供有關腳本中其他變數的重要信息。下麵介紹 bash 變數和一些特殊 ...
    • Qt C++界面開發過程中,使用自定義的QGroupBox類,重寫繪圖事件paintEvent時,出現邊框被覆蓋的情況,或邊框消失的問題。 ...
    • 來源:https://juejin.cn/post/7123091045071454238 一個優秀的 Controller 層邏輯 說到 Controller,相信大家都不陌生,它可以很方便地對外提供數據介面。它的定位,我認為是「不可或缺的配角」。 說它不可或缺是因為無論是傳統的三層架構還是現在的 ...
    • 一. anaconda 簡介 Anaconda是一個開源的Python發行版本,用來管理Python相關的包,安裝Anaconda可以很方便的切換不同的環境,使用不同的深度學習框架開發項目。 二. anaconda 下載地址 anaconda 官網地址: https://www.anaconda.c ...
    • 代碼里我們經常會出現大量的條件判斷,在這種情況下,我們可以實現狀態機避免過度使用 有一種方式是把各種狀態歸為各種狀態類 還有一種方式是修改實例的__class__屬性 1 """ 2 狀態機的實現 3 修改實例的__class__屬性 4 """ 5 6 7 class Connection: 8 ...
    • JZ47 禮物的最大價值 描述 描述 在一個m\times nm×n的棋盤的每一格都放有一個禮物,每個禮物都有一定的價值(價值大於 0)。你可以從棋盤的左上角開始拿格子里的禮物,並每次向右或者向下移動一格、直到到達棋盤的右下角。給定一個棋盤及其上面的禮物的價值,請計算你最多能拿到多少價值的禮物? 如 ...
    • 面向對象 1.面向對象簡介 類(Class): 用來描述具有相同的屬性和方法的對象的集合。它定義了該集合中每個對象所共有的屬性和方法。對象是類的實例。 方法:類中定義的函數。 類變數:類變數在整個實例化的對象中是公用的。類變數定義在類中且在函數體之外。類變數通常不作為實例變數使用。 數據成員:類變數 ...
    • 一:背景 1.講故事 今天是🐏的第四天,頭終於不巨疼了,寫文章已經沒什麼問題,趕緊爬起來寫。 這個月初有位朋友找到我,說他的程式出現了CPU爆高,讓我幫忙看下怎麼回事,簡單分析了下有兩點比較有意思。 這是一個安全生產的信息管理平臺,第一次聽說,我的格局小了。 這是一個經典的 CPU 爆高問題,過往 ...
    一周排行
      -Advertisement-
      Play Games
    • Dapr Outbox 是1.12中的功能。 本文只介紹Dapr Outbox 執行流程,Dapr Outbox基本用法請閱讀官方文檔 。本文中appID=order-processor,topic=orders 本文前提知識:熟悉Dapr狀態管理、Dapr發佈訂閱和Outbox 模式。 Outbo ...
    • 引言 在前幾章我們深度講解了單元測試和集成測試的基礎知識,這一章我們來講解一下代碼覆蓋率,代碼覆蓋率是單元測試運行的度量值,覆蓋率通常以百分比表示,用於衡量代碼被測試覆蓋的程度,幫助開發人員評估測試用例的質量和代碼的健壯性。常見的覆蓋率包括語句覆蓋率(Line Coverage)、分支覆蓋率(Bra ...
    • 前言 本文介紹瞭如何使用S7.NET庫實現對西門子PLC DB塊數據的讀寫,記錄了使用電腦模擬,模擬PLC,自至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1.Windows環境下鏈路層網路訪問的行業標準工具(WinPcap_4_1_3.exe)下載鏈接:http ...
    • 從依賴倒置原則(Dependency Inversion Principle, DIP)到控制反轉(Inversion of Control, IoC)再到依賴註入(Dependency Injection, DI)的演進過程,我們可以理解為一種逐步抽象和解耦的設計思想。這種思想在C#等面向對象的編 ...
    • 關於Python中的私有屬性和私有方法 Python對於類的成員沒有嚴格的訪問控制限制,這與其他面相對對象語言有區別。關於私有屬性和私有方法,有如下要點: 1、通常我們約定,兩個下劃線開頭的屬性是私有的(private)。其他為公共的(public); 2、類內部可以訪問私有屬性(方法); 3、類外 ...
    • C++ 訪問說明符 訪問說明符是 C++ 中控制類成員(屬性和方法)可訪問性的關鍵字。它們用於封裝類數據並保護其免受意外修改或濫用。 三種訪問說明符: public:允許從類外部的任何地方訪問成員。 private:僅允許在類內部訪問成員。 protected:允許在類內部及其派生類中訪問成員。 示 ...
    • 寫這個隨筆說一下C++的static_cast和dynamic_cast用在子類與父類的指針轉換時的一些事宜。首先,【static_cast,dynamic_cast】【父類指針,子類指針】,兩兩一組,共有4種組合:用 static_cast 父類轉子類、用 static_cast 子類轉父類、使用 ...
    • /******************************************************************************************************** * * * 設計雙向鏈表的介面 * * * * Copyright (c) 2023-2 ...
    • 相信接觸過spring做開發的小伙伴們一定使用過@ComponentScan註解 @ComponentScan("com.wangm.lifecycle") public class AppConfig { } @ComponentScan指定basePackage,將包下的類按照一定規則註冊成Be ...
    • 操作系統 :CentOS 7.6_x64 opensips版本: 2.4.9 python版本:2.7.5 python作為腳本語言,使用起來很方便,查了下opensips的文檔,支持使用python腳本寫邏輯代碼。今天整理下CentOS7環境下opensips2.4.9的python模塊筆記及使用 ...