csharp
<TextBlock Text="{Binding IsGrowing,Converter={StaticResource BoolToBrushConverter}}"
Grid.Column="1" VerticalAlignment="Center" Margin="10,0,0,0"
Foreground="{Binding IsGrowing,Converter={StaticResource BoolToBrushConverter}}"/>

csharp
<TextBlock Text="{Binding SeriesName}" VerticalAlignment="Center"/>
<TextBlock Text="{Binding CurrentValue}" Grid.Row="1" VerticalAlignment="Center"/>
<TextBlock Text="{Binding IsGrowing,Converter={StaticResource BoolToBrushConverter}}"
Grid.Column="1" VerticalAlignment="Center" Margin="10,0,0,0"
Foreground="{Binding IsGrowing,Converter={StaticResource BoolToBrushConverter}}"/>
<TextBlock Text="{Binding ChangeRate,StringFormat=\{0\}%}" Grid.Column="1" Grid.Row="1"
VerticalAlignment="Center" Margin="10,0,0,0"
Foreground="{Binding IsGrowing,Converter={StaticResource BoolToBrushConverter}}"/>
```
```csharp
<Hyperlink Foreground="#333"
Command="{Binding DataContext.OpenCourseUrlCommand,
RelativeSource={RelativeSource AncestorType=UserControl,Mode=FindAncestor }}"
CommandParameter="{Binding Url}">
<Hyperlink.Style>
<Style>
<Setter Property="TextBlock.TextDecorations" Value="{x:Null}"/>
<Style.Triggers>
<Trigger Property="Hyperlink.IsMouseOver" Value="True">
<Setter Property="TextBlock.TextDecorations">
<Setter.Value>
<TextDecorationCollection>
<TextDecoration Location="Underline"/>
</TextDecorationCollection>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Hyperlink.Style>

csharp
<ItemsControl Margin="15,0" ItemsSource="{Binding Teachers}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Background="#EEE" Margin="5,0" CornerRadius="5">
<TextBlock Text="{Binding}" Margin="12,3"/>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

csharp
<ItemsControl Margin="15,0" ItemsSource="{Binding Teachers}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Background="#EEE" Margin="5,0" CornerRadius="5">
<TextBlock Text="{Binding}" Margin="12,3"/>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
具体是怎么绑定的
CoursePageView → DataContext → CoursePageViewModel → CourseList → 单个CourseModel → Teachers
csharp
public partial class CoursePageView : UserControl
{
public CoursePageView()
{
InitializeComponent();
this.DataContext = new CoursePageViewModel(); // 关键!设置数据上下文
}
}

csharp
<ItemsControl.ItemTemplate>
<DataTemplate>
<RadioButton Content="{Binding CategoryName}" IsChecked="{Binding IsSelected}"
Template="{StaticResource CategoryItemButtonTemplate}"
Margin="5,0" GroupName="course"/>
</DataTemplate>
</ItemsControl.ItemTemplate>Binding CategoryName的数据流程







csharp
[数据源头]
CategoryCourses集合
↓ (包含3个CategoryItemModel对象)
├─ {CategoryName:"全部", IsSelected:true}
├─ {CategoryName:"公开课", IsSelected:false}
└─ {CategoryName:"Vip课程", IsSelected:false}
↓ (ItemsControl遍历绑定)
[界面生成]
RadioButton组显示:
○ 全部 ○ 公开课 ○ Vip课程
(选中) (未选中) (未选中)
csharp
<TextBlock Text="{Binding Description}"
TextWrapping="Wrap" LineHeight="23" Foreground="#AAA"/>{Binding Description}
的数据流程
csharp
[数据源头]
数据库课程表
↓ (SQL查询)
LocalDataAccess.GetCourses()
↓ (返回List<CourseModel>)
CoursePageViewModel.courseAll
↓ (填充到可观察集合)
CoursePageViewModel.CourseList (ObservableCollection<CourseModel>)
↓ (ItemsControl绑定)
ItemsControl.ItemsSource="{Binding CourseList}"
↓ (DataTemplate应用)
当前项的DataContext = CourseModel对象
↓ (属性绑定)
TextBlock.Text="{Binding Description}"
↓ (界面显示)
课程描述文本
csharp
ItemsControl.ItemTemplate>
<DataTemplate>
<RadioButton Content="{Binding CategoryName}" IsChecked="{Binding IsSelected}" Template="{StaticResource CategoryItemButtonTemplate}" Margin="5,0"
GroupName="course"/>
</DataTemplate>
</ItemsControl.ItemTemplate>{Binding CategoryName}的数据流程
用C#和WPF做的漂亮界面、与设备通讯的控制逻辑、与数据库交互的数据管理模块,这三者组合在一起,就形成了一个完整的 "基于软件的设备控制程序"------也就是一个功能强大的上位机软件。







总结与工作流程
把这个"遥控器"用起来,一个典型的串口通信流程是:
准备阶段:用 GetPortNames找到可用的串口,创建一个 SerialPort对象。
配置阶段:根据设备手册,设置好 PortName、BaudRate等所有属性。
设置监听:为 DataReceived事件挂接上你的"数据处理函数"。
建立连接:调用 Open()方法。
自动响应:之后,只要设备发来数据,你的"数据处理函数"就会自动运行,在里面调用 Read()读取数据并处理。
主动发送:需要时,调用 Write()给设备发送命令。
结束工作:通信完成后,调用 Close()关闭连接。
记住最关键的一点:在 DataReceived事件触发的函数里操作界面控件(比如更新一个文本框)时,因为它在另一个线程,必须通过 Invoke方法来安全地更新UI,否则程序会崩溃。
winform
System.NullReferenceException
HResult=0x80004003
Message=未将对象引用设置到对象的实例。
Source=WindowsFormsApp1
StackTrace:
at WindowsFormsApp1.FormMain.FormMain_Load(Object sender, EventArgs e) in D:\vsprogram\WinBookKeeping\WindowsFormsApp1\WindowsFormsApp1\FormMain.cs:line 28
c#
引用类型
对象类型

装箱 拆箱

csharp
int i = 100; // i 是一个值类型,存储在栈上
// 装箱操作(对应你总结的三个步骤)
object obj = i; // 将 i 装箱,obj 是一个引用类型,指向堆上的对象
Console.WriteLine($"原始值: {i}"); // 输出: 原始值: 100
Console.WriteLine($"装箱后的值: {obj}"); // 输出: 装箱后的值: 100
// 修改原始值
i = 200;
Console.WriteLine($"修改后 i 的值: {i}"); // 输出: 修改后 i 的值: 200
Console.WriteLine($"修改后 obj 的值: {obj}"); // 输出: 修改后 obj 的值: 100
// 可见,修改 i 不会影响 obj,因为它们是两份独立的数据。
// 拆箱操作 (Unboxing)
// 将引用类型 obj 转换回原始的值类型 int
int j = (int)obj; // 拆箱
Console.WriteLine($"拆箱后的值: {j}"); // 输出: 拆箱后的值: 100
动态类型(dynamic)
字符串类型(string)
csharp
//使用""声明
"Jack" ;string sname二
//使用@""声明
string path="d:\lfolderllimgs";
string path = @"d:\folder\imgs";
值类型


派生类

csharp
// 基类
public class Animal
{
public string Name { get; set; }
public void Eat()
{
Console.WriteLine($"{Name} is eating.");
}
}
// 派生类
public class Dog : Animal // Dog 继承自 Animal
{
public void Bark()
{
Console.WriteLine("Woof! Woof!");
}
}
csharp
Dog myDog = new Dog();
myDog.Name = "Buddy"; // 继承自基类的属性
myDog.Eat(); // 调用继承自基类的方法
myDog.Bark(); // 调用派生类自己的方法
winform

协议
csharp
using System.IO.Ports;
namespace CommComponent
{
internal class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello, World!");
string[] ports=SerialPort.GetPortNames();
SerialPort serialPort = new SerialPort();
serialPort.PortName = "COM2";
serialPort.BaudRate = 9600;
serialPort.DataBits = 8;
serialPort.Parity = Parity.None;
serialPort.StopBits= StopBits.None;
serialPort.Open();
serialPort.Close();
}
}
}








