需求是这样的,系统要监测风,雨,雪多个自然灾害。在界面上有这些灾害突发的报警框。本来报警框的背景是由于级别不同显示不同的颜色,但是现在发现,当报警背景为蓝色是,黑色字体 看不出来。又由于技术文档上规定背景颜色了,所以现在只能改变所有lbl的字体。而这些控件都是WPF自定义控件的一些 元素。
要实现这个功能,有很多种方式。WPF的好处 就是既可以像Html+CSS 去设置, 也可以像Winform一样去更改。重点说一下解决方式。
这个功能要调用的有大概10多处,每个窗体有6个左右lbl,所以每次给每个控件挨个赋值是绝对不能用的。
先看一下样式和自定义控件代码。
样式:
<span style="font-family:KaiTi_GB2312;"> <UserControl x:Class="ICT.RCS.Modules.SingleLine.Facilities.UserControlFile.ucSnowAlert"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="150" d:DesignWidth="340" BorderThickness="1" BorderBrush="#AAAAAA">
<Grid x:Name="grdSnowAlert" Height="150">
<Grid.Resources >
<Style TargetType="Label" >
<Setter Property="FontSize" Value="12"/>
<Setter Property="Foreground" Value="{Binding FontColorBrush,UpdateSourceTrigger=PropertyChanged}"/>
<Setter Property="Background" Value="{Binding FontColorBrush,UpdateSourceTrigger=PropertyChanged}"/>
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="VerticalAlignment" Value="Center"></Setter>
<Setter Property="FontFamily" Value="Microsoft YaHei"/>
</Style>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height=" 30" ></RowDefinition>
<RowDefinition Height=" 30" ></RowDefinition>
<RowDefinition Height=" 30" ></RowDefinition>
<RowDefinition Height=" 30"></RowDefinition>
<RowDefinition Height=" 30"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60*"></ColumnDefinition>
<ColumnDefinition Width="100*"></ColumnDefinition>
<ColumnDefinition Width="60*"></ColumnDefinition>
<ColumnDefinition Width="120*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Content="雪 深 报 警" Width="322" HorizontalAlignment="Center" FontWeight="Bold" Grid.ColumnSpan="4" Margin="0,4,0,0" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Height="27"/>
<Border Grid.Column="0" BorderThickness="0,1,1,1" BorderBrush="#AEAEAE" Grid.Row="1" >
<Label Content="监测点" HorizontalAlignment="Center" Margin="5,-2,5,2"/>
</Border>
<Border Grid.Row=" 1" Grid.Column=" 2" BorderBrush="#AEAEAE" BorderThickness="1">
<Label Content="报警时间" HorizontalAlignment="Center" />
</Border>
<Border Grid.Row=" 2" Grid.Column="0" BorderBrush="#AEAEAE" BorderThickness="0,0,1,1">
<Label Content="影响区间" HorizontalAlignment="Center" />
</Border>
<Border Grid.Row=" 3" Grid.Column=" 0" BorderBrush="#AEAEAE" BorderThickness ="0,0,1,1">
<Label Content="限速区段" HorizontalAlignment="Center" Margin="0,-1,0,1"/>
</Border>
<Border Grid.Column="1" BorderBrush="#AEAEAE" BorderThickness ="0,1,0,1" Grid.Row="1">
<Label x:Name="lblSnowCheckPoint" Content="" Margin="0,0,-1,0" Width="100" />
</Border>
<Border Grid.Row="1" Grid.Column=" 3" BorderBrush="#AEAEAE" BorderThickness ="0,1,0,1">
<Label x:Name="lblSnowAlarmTime" Content="" Margin="0,-1,0,1"/>
</Border>
<Border Grid.Row=" 2" Grid.Column=" 1" Grid.ColumnSpan=" 3" BorderBrush="#AEAEAE" BorderThickness ="0,0,0,1">
<Label x:Name="lblSnowEffectArea" Content="" />
</Border>
<Border Grid.Row=" 3" Grid.Column=" 1" BorderBrush="#AEAEAE" BorderThickness ="0,0,0,1">
<Label x:Name="lblSnowLockArea" Content="" />
</Border>
<Border Grid.Row=" 3" Grid.Column=" 2" BorderBrush="#AEAEAE" BorderThickness="1,0,1,1">
<Label Content="处置措施" HorizontalAlignment="Center" Foreground="Black"/>
</Border>
<Border Grid.Row="3" Grid.Column=" 3" BorderBrush="#AEAEAE" BorderThickness ="0,0,0,1">
<Label x:Name="lblSnowCommand" Content="" />
</Border>
<Button x:Name="btnAlert" Grid.ColumnSpan="4" Content="报 警 确 认" Grid.Column="0" HorizontalAlignment="Center" Height="20" Grid.Row="4" VerticalAlignment="Center" Width="75" Margin="0" Click="Button_Click" IsEnabled="False"/>
</Grid>
</UserControl>
</span>
现在界面是这样的。
解决方案:
我采用的通过判断控件的属性来赋值。这和vb是相通的,只不过需要属性一下 几个控件都有哪些属性。谁有什么节点等。
<span style="font-family:KaiTi_GB2312;">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace ChildDemo
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : UserControl
{
private SolidColorBrush sBush = new SolidColorBrush();
public MainWindow()
{
InitializeComponent();
this.ChangeLblColor(this.grdRainAlert.Children, 2);
}
#region 根据警报状态更改报警框中字体颜色--2015-7-31
/// <summary>
/// 根据警报状态更改报警框中字体颜色
/// </summary>
/// <param name="uiControls">Gride(报警框)的子节点</param>
/// <param name="alermStatus">报警状态</param>
public void ChangeLblColor(UIElementCollection uiControls, int alermStatus)
{
if (uiControls != null)
//遍历每个级别的控件,当控件类型为lbl 并且状态为2时,改变字体颜色为白。
foreach (UIElement element in uiControls)
{
if (element is Label)
switch (alermStatus)
{
case 2:
(element as Label).Foreground = new SolidColorBrush(Colors.White);
break;
default:
(element as Label).Foreground = new SolidColorBrush(Colors.Black);
break;
}
else if (element is Border && (element as Border).Child is Label) //如果该控件为border,border的子节点是lbl
{
Label lbl = (Label)(element as Border).Child;
switch (alermStatus)
{
case 2:
lbl.Foreground = new SolidColorBrush(Colors.White);
break;
default:
lbl.Foreground = new SolidColorBrush(Colors.Black);
break;
}
}
}
return;
}
#endregion
}
}
</span>
以上是一种应用。这个方法如果针对其他情况还不是很好用,其实还可以抽象出一个万能方法。
正好总结的时候浏览到 一篇这样的博客。觉得总结的很详细。 拿出来分享一下~
------------------------------------------------------------------------------以下为摘抄---------------------------------------------------
c#winform中遍历控件,界面具有Controls属性,可以直接进行遍历访问:
<span style="font-family:KaiTi_GB2312;">在百度上看到很多人采用:
foreach (UIElement element in this.Control.Children)
{
if (element is UserControl)
{
UserControl current = ((UserControl)element);
}
}</span>
但是,通过使用,可以发现其中的问题:
不是每一个Control都具有Children属性,如果遍历对象是Grid、StackPanl那么是可以实现,但只能遍历当前Grid的子控件,对当前控件的子控件中的子控件则无法实现遍历,如
<span style="font-family:KaiTi_GB2312;"><grid name ="Parent">
<grid name ="son"/>
<grid name ="son2">
<grid name = "son3"/>
</grid>
</grid>
</span>
则只能遍历到son和son2,对son3束手无策,递归是吧? 在这个小例子中,递归ok,但若是下面的呢?
<span style="font-family:KaiTi_GB2312;"> <grid name ="Parent">
<grid name ="son"/>
<grid name ="son2">
<StackPanl name = "panl"/>
<grid name ="son3"/>
</StackPanl >
</grid></span>
StackPanl不具有children属性,因此你无法对其进行遍历。
但是问题仍然可以进行解决:
重点来了:
<span style="font-family:KaiTi_GB2312;"> /// <summary>
/// 功 能:遍历界面所有TextBox,设置IsEnable属性为False
/// 作 者:Liu Hao | 日期:2012年5月30日
/// </summary>
/// <param name="uiControls"></param>
private void SetNotEditable(UIElementCollection uiControls)
{
foreach (UIElement element in uiControls)
{
if (element is TextBox)
{
(element as TextBox).IsEnabled = false;
}
else if (element is Grid)
{
this.SetNotEditable((element as Grid).Children);
}
else if (element is Expander)
{
//此代码仅供参考
//在您的布局中,Expander或者其他不具有Children属性的控件的Content,若不是StackPanl或Grid,而是其他的子控件,则需要更多的判断
if ((element as Expander).Content is StackPanel)
{
StackPanel sa = (element as Expander).Content as StackPanel;
this.SetNotEditable(sa.Children);
}
else if ((element as Expander).Content is Grid)
{
Grid sa = (element as Expander).Content as Grid;
this.SetNotEditable(sa.Children);
}
}
else if (element is StackPanel)
{
this.SetNotEditable((element as StackPanel).Children);
}
else if (element is ScrollViewer)
{
StackPanel sp = (element as ScrollViewer).Content as StackPanel;
this.SetNotEditable(sp.Children);
//ScrollViewer不具有Children属性,无法对其进行遍历,但是具有Content属性,作为容器型控件,一般都可以通过这样的方法来解决。
}
}
}
//在事件中进行调用
private void btnQuery_Click(object sender, RoutedEventArgs e)
{
this.SetNotEditable(this.gridUCContent.Children); //gridUCContent为最顶层Grid
}
</span>
此代码及讲解仅作为参考,代码主要针对上面我自己的Xaml中的布局。不能直接粘贴引用,但可以提供思路。
-------------------------------------------------------------------------------------------
这是一种类似Winform的实现方式,最近在研究WPF的画刷和绑定,目测通过这种方式也能实现。 最初自己以为WPF就是简单的拖拽控件,现在发现如果只会简单的拖拽控件,是连一个最基本的简单的小系统都无法完成。它相当于既有Winform的拖拽性质,也有BS的网页制作的性质。而且界面能做出很炫很精确的效果,目前还在 研究。当然也有一个弊端就是WPF只有界面和后台两个进程,导致现在由于前台处理的数据比较多,界面也用到大量的委托 比较慢,目前还不知有有什么解决的办法,都在研究中。
知识的相通性体会很深~