调用线程无法访问此对象,因为另一个线程拥有该对象

线程中操作界面相关的内容时会出现这个问题

Dispatcher.Invoke(new Action(
() => { dg.ItemsSource = protocol.List_sensor; }));
阅读全文 »

产生指定上限的随机数

Random ran = new Random();

int n = ran.Next(100);

产生指定上下限的随机数

Random ran = new Random();

int n = ran.Next(100, 1000);

用 Random 结合数组产生指定范围随机数

public string GetRandom(string[] arr)
{
Random ran = new Random();
int n = ran.Next(arr.Length - 1);
return arr[n];
}

调用方法:

string[] arr = { "25", "28", "30", "50", "60" };
GetRandom(arr);

用 Random 产生小数随机数

public double NextDouble(Random ran, double minValue, double maxValue)
{
return ran.NextDouble() * (maxValue - minValue) + minValue;
}

Random ran = new Random();
double randNum = NextDouble(ran, 1.52, 2.65);
Response.Write(randNum);// 结果 2.30927768119112

// 保留指定位数
public double NextDouble(Random ran, double minValue, double maxValue, int decimalPlace)
{
double randNum = ran.NextDouble() * (maxValue - minValue) + minValue;
return Convert.ToDouble(randNum.ToString("f" + decimalPlace));
}

Random ran = new Random();
double randNum = NextDouble(ran, 5.16, 8.68, 2);// 保留两位小数
Response.Write(randNum);// 结果 8.46

产生相对不重复的随机数

System.Security.Cryptography命名空间下提供一个名为RNGCryptoServiceProvider的类,它采用系统当前的硬件信息、进程信息、线程信息、系统启动时间和当前精确时间作为填充因子,通过更好的算法生成高质量的随机数

byte[] randomBytes = new byte[4];
RNGCryptoServiceProvider rngServiceProvider = new RNGCryptoServiceProvider();
rngServiceProvider.GetBytes(randomBytes);
Int32 result = BitConverter.ToInt32(randomBytes, 0);

null conditional operator

drawMethodsDelegate?.Invoke ( e.Graphics );

回调函数

// 接收函数回调
public delegate int OnRecieve(string msg, string param = "");
public OnRecieve CBRecieve = null;

public void SetCallBackRecieve(OnRecieve cb)
{
CBRecieve = cb;
}

CBRecieve?.Invoke(last_response_msg);

gratingscale.SetCallBackRecieve(OnRecieveGratingscale);

public int OnRecieveGratingscale(string msg, string param = "")
{

return 0;
}

msdn

Dictionary

//Dictionary<TKey,TValue>
Dictionary<string,Model_driver> cur_driver = new Dictionary<string, Model_driver>();
if (cur_driver.ContainsKey(it.Name))
{
...
}

SortedDictionary<TKey, TValue>

// Create a new dictionary of strings, with string keys.
//
Dictionary<string, string> openWith =
new Dictionary<string, string>();

// If a key does not exist, setting the indexer for that key
// adds a new key/value pair.
openWith["doc"] = "winword.exe";

// Add some elements to the dictionary. There are no
// duplicate keys, but some of the values are duplicates.
openWith.Add("txt", "notepad.exe");
openWith.Add("bmp", "paint.exe");
openWith.Add("dib", "paint.exe");
openWith.Add("rtf", "wordpad.exe");

// The indexer can be used to change the value associated
// with a key.
openWith["rtf"] = "winword.exe";

// ContainsKey can be used to test keys before inserting
// them.
if (!openWith.ContainsKey("ht"))
{
openWith.Add("ht", "hypertrm.exe");
Console.WriteLine("Value added for key = \"ht\": {0}",
openWith["ht"]);
}
阅读全文 »

项目中新建文件夹 Images,资源管理器中把图片拷贝进去,项目中图片属性设置 build action 为 Resource do not copy 就可以引用了。

<ToolBarTray DockPanel.Dock="Top">
<ToolBar>
<Button ToolTip="打开测量界面" Name="tb_measurement" Click="tb_measurement_Click">
<StackPanel Orientation="Vertical">
<Image Source="/MRLGauger;component/Images/measure_40.png" />
<TextBlock Margin="0,2,0,0" HorizontalAlignment="Center">测量</TextBlock>
</StackPanel>
</Button>
<Button ToolTip="打开编程界面" Name="tb_program" Click="tb_program_Click">
<StackPanel Orientation="Vertical">
<Image Source="/MRLGauger;component/Images/measure_40.png" />
<TextBlock Margin="0,2,0,0" HorizontalAlignment="Center">编程</TextBlock>
</StackPanel>
</Button>
<Button Command="Save" Content="Save" />
</ToolBar>
</ToolBarTray>

动态切换图标和文字

<Window x:Class="MRLGauger.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MRLGauger"
mc:Ignorable="d" Loaded="Window_Loaded"
Title="MRLGauger" Height="768" Width="1024" WindowStartupLocation="CenterScreen" Closed="Window_Closed">
<Window.Resources>
<StackPanel x:Key="IMG_Auto" Orientation="Vertical">
<Image Source="/MRLGauger;component/Images/auto_40.png" />
<TextBlock Margin="0,2,0,0" HorizontalAlignment="Center">自动</TextBlock>
</StackPanel>
<StackPanel x:Key="IMG_Manual" Orientation="Vertical">
<Image Source="/MRLGauger;component/Images/manual_40.png" />
<TextBlock Margin="0,2,0,0" x:Name="tb_textBlock_manual" HorizontalAlignment="Center">手动</TextBlock>
</StackPanel>
</Window.Resources>
...


private void tb_auto_Click(object sender, RoutedEventArgs e)
{
// 1 自动(默认), 2 手动
if (measureDisplay.operate_type == 1)
{
measureDisplay.operate_type = 2;
((Button)sender).Content = FindResource("IMG_Manual");
}
else if (measureDisplay.operate_type == 2)
{
measureDisplay.operate_type = 1;
((Button)sender).Content = FindResource("IMG_Auto");
}

tb_textBlock_manual.Text = "文字";

}

设置无效

<Button ToolTip="开始自动测量" Name="tb_start" Click="tb_start_Click">
<StackPanel Orientation="Vertical">
<Image x:Name="img_start" Source="{DynamicResource src_img_start}" />
<TextBlock Margin="0,2,0,0" HorizontalAlignment="Center">工步开始</TextBlock>
</StackPanel>
</Button>

// 设置灰度图
{
ImageSource isource = img_start.Source;
FormatConvertedBitmap fcb = new FormatConvertedBitmap((BitmapSource)isource, PixelFormats.Gray32Float, null, 0);
img_start.Source = fcb;
img_start.OpacityMask = new ImageBrush(isource);
}

// 回复原图
img_start.Source = FindResource("src_img_start") as BitmapImage;

每个文件都有一个 build action 用来控制资源文件的使用

msdn

  • Resource Files: Data files that are compiled into either an executable or library WPF assembly.
  • Content Files: Standalone data files that have an explicit association with an executable WPF assembly.
  • Site of Origin Files: Standalone data files that have no association with an executable WPF assembly.

项目中新建文件夹 Images,资源管理器中把图片拷贝进去,项目中图片属性设置 build action 为 Resource do not copy 就可以引用了。

<ToolBarTray DockPanel.Dock="Top">
<ToolBar>
<Button ToolTip="打开测量界面" Name="tb_measurement" Click="tb_measurement_Click">
<StackPanel Orientation="Vertical">
<Image Source="/MRLGauger;component/Images/measure_40.png" />
<TextBlock Margin="0,2,0,0" HorizontalAlignment="Center">测量</TextBlock>
</StackPanel>
</Button>
<Button ToolTip="打开编程界面" Name="tb_program" Click="tb_program_Click">
<StackPanel Orientation="Vertical">
<Image Source="/MRLGauger;component/Images/measure_40.png" />
<TextBlock Margin="0,2,0,0" HorizontalAlignment="Center">编程</TextBlock>
</StackPanel>
</Button>
<Button Command="Save" Content="Save" />
</ToolBar>
</ToolBarTray>

Window.Resources

how-to-use-a-bitmapimage

<Image Width="200">
<Image.Source>
<!-- To save significant application memory, set the DecodePixelWidth or
DecodePixelHeight of the BitmapImage value of the image source to the desired
height and width of the rendered image. If you don't do this, the application will
cache the image as though it were rendered as its normal size rather then just
the size that is displayed. -->
<!-- Note: In order to preserve aspect ratio, only set either DecodePixelWidth
or DecodePixelHeight but not both. -->
<BitmapImage DecodePixelWidth="200"
UriSource="C:\Documents and Settings\All Users\Documents\My Pictures\Sample Pictures\Water Lilies.jpg" />
</Image.Source>
</Image>

image vs BitmapImage

Image is a skinnable class that wraps BitmapImage. As such BitmapImage is more lightweight, but Image has more features. So the question when to use which boils down to this:
if the features of BitmapImage suffice, use that; otherwise use Image. Especially in mobile environments try to favor the use of BitmapImage.

Now what features does Image add exactly?

Image extends SkinnableComponent: this means you can assign your images a skin with a border or a dropshadow or whatever you like consistently throughout your application.
It also provides a progress indicator which can be displayed while the image is loading.
One more feature is the possibility to queue the loading of multiple images.

全局字体和尺寸

<Application.Resources>
<Style TargetType="{x:Type TextElement }">
<Setter Property="FontFamily" Value="Comic Sans MS"/>
<Setter Property="FontSize" Value="30"/>
</Style>
<Style TargetType="{x:Type TextBlock }">
<Setter Property="FontFamily" Value="Comic Sans MS"/>
<Setter Property="FontSize" Value="30"/>
</Style>
</Application.Resources>

样例类

public class Model_driverProtocolSensorSimulator
{
[JsonIgnore]
public const int CMD_TYPE_LOGIN = 1;
[JsonIgnore]
public const int CMD_TYPE_SENSOR_INFO = 2;
[JsonIgnore]
public const int CMD_TYPE_SENSOR_DATA = 3;

public int CmdType;
public List<Model_driverSensor> List_sensor = new List<Model_driverSensor>();
public string Param;
}

生成json字符串

var var_list = $"t{file_index}";
var strArr = new JArray { var_list };
var obj = new JObject{ {"type","datas" },{ "size",file_size},{ "var_name_list",strArr},{ "trans_type",trans_type},{"pre_formula",preFormula },
{ "preelaboration",preelabration},{ "formula",formula},{"elaboration",elaboration } };
string param = obj.ToString();

// without formatting
string strResponse = ws.CheckUser("", jsonObj.ToString(Formatting.None));
// object to json string
Newtonsoft.Json.JsonConvert.SerializeObject(new {foo = "bar"})


阅读全文 »

xmlns:sys="clr-namespace:System;assembly=mscorlib"

<DatePicker x:Name="datePickerCtl" SelectedDate="{x:Static sys:DateTime.Now}"
SelectedDateFormat="Short" FirstDayOfWeek="Monday"
IsTodayHighlighted="True" Grid.Row="0" Grid.Column="1">
<DatePicker.Resources>
<Style TargetType="{x:Type DatePickerTextBox}">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<TextBox x:Name="PART_TextBox"
Text="{Binding Path=SelectedDate, StringFormat='yyyy-MM-dd',
RelativeSource={RelativeSource AncestorType={x:Type DatePicker}}}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DatePicker.Resources>
</DatePicker>


datePickerCtl.SelectedDate = DateTime.Now;

var strDate = datePickerCtl.SelectedDate.Value.ToString("yyyy-MM-dd");

获取主程序(主窗口)对象

Window mainwin = Application.Current.MainWindow;
MessageBox.Show(mainwin.Title, mainwin.Title);

((TESTAPP.MainWindow)Application.Current.MainWindow).nng_python.test();

改变主窗口大小

```

## 窗口置顶

```c#
private void chk_ontop_Click(object sender, RoutedEventArgs e)
{
if (App.db.m_config[0].OnTop)
{
Topmost = true;
}
else
{
Topmost = false;
}
App.db.Update_model(App.db.m_config[0]);
}

判断当前的 UC 控件

if (grid_main.Children[0] is MRLGauger.uc.UCMeasureDisplay)
{
measurDisplay = (UCMeasureDisplay)grid_main.Children[0];
if (UCMeasureDisplay.FLAG_PLUGIN_DATA_PROC_LOGIN != (measurDisplay.flag& UCMeasureDisplay.FLAG_PLUGIN_DATA_PROC_LOGIN))
{
MessageBox.Show("算法驱动尚未加载,请检查程序是否正常。");
return;
}
}

启动居中

// xml 里面添加
WindowStartupLocation="CenterScreen"

支持Winforms

// 编辑项目文件
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0-windows</TargetFramework>
<UseWPF>true</UseWPF>
<UseWindowsForms>true</UseWindowsForms>
<Platforms>AnyCPU;x64</Platforms>
</PropertyGroup>

关闭窗体

//关闭当前窗体
this.Close();

// 关闭所有窗体
Application.Current.Shutdown();

程序图标

工程上右键——属性——应用程序——图标和清单,选刚才的那个图标
需要 ico 图片

版本和版权信息

项目右键-属性 里面

Visibility可视性属性

有三种值:Collapsed、Hidden、Visible。

Hidden仅仅是属性设为不可视,但是属性在画面上依然占有空间。
Collapsed,在不可视的基础上,它还能将属性在画面上的占位符清除,属性将彻底不影响画面。所以,某些时候使用Collapsed将更为合理。

例如:在StackPanel中使用该属性的时候最为明显。三个对象在同一个StackPanel中,中间的对象如果Hidden,还将占有Stack中的位置,而Collapsed的话,下面的对象就会挤上来,占据中间对象的位置。