WPF 自制扫雷,用到蛮多东西,记录下来

exe不能下载的话源码里有,资源绑定默认是vip资源,不知道你们能不能下载。
只换一个积分的源码
点我下载

主窗口关闭,程序不退出的问题

WPF 主窗口默认是MainWindow,但是点击主窗口的关闭按钮(X)窗口关闭了,程序未退出。
解决办法:在MainWindow.xaml中Window标签里添加Closing事件函数
Closing=“Window_Closing”
然后在Window_Closing方法中添加
Application.Current.Shutdown();
这样,在主窗口关闭的时候,会关闭整个程序
PS:此方法不能关闭某些子线程,可以在此之前手动关闭,或者使用
Environment.Exit(0);
具体区别点我

子窗口关闭,直接窗口被删除了,而不是隐藏

解决办法:
还是Closing=“Window_Clising”

private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
     e.Cancel = true;
     Hide();
}

键盘按键事件

Window控件有KeyDown、KeyUp、PreviewKeyDown、PreviewKeyUp
对我来说只用KeyDown事件就可以了

private void Window_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyStates == Keyboard.GetKeyStates(Key.F2))
    {
    	MenuItem_Click(Menu_NewGame, new RoutedEventArgs());
    }
}

菜单与菜单点击事件

Xaml中的使用方式:
在Window标签下Grid中

<Menu Grid.Row="0" Background="White">
            <MenuItem x:Name="Menu_Game" Header="游戏">
                <MenuItem x:Name="Menu_NewGame" Header="新游戏(F2)" Click="MenuItem_Click"/>
                <Separator />
                <MenuItem x:Name="Menu_Statistics" Header="统计信息(F3)" Click="MenuItem_Click"/>
                <MenuItem x:Name="Menu_Options" Header="选项(F4)" Click="MenuItem_Click"/>
                <Separator />
                <MenuItem x:Name="Menu_Exit" Header="退出(Alt + F4)" Click="MenuItem_Click"/>
            </MenuItem>
            <MenuItem x:Name="Menu_Help" Header="帮助">
                <MenuItem x:Name="Menu_ViewHelp" Header="查看帮助(F1)" Click="MenuItem_Click"/>
                <MenuItem x:Name="Menu_About" Header="关于扫雷" Click="MenuItem_Click"/>
            </MenuItem>
        </Menu>

Menu中每个MenuItem是一列,MenuItem中的MenuItem会点击展开。
是间隔线
效果如下图所示
在这里插入图片描述

菜单点击事件

我是根据MenuItem的名字属性区分点了哪个

 		private void MenuItem_Click(object sender, RoutedEventArgs e)
        {
            MenuItem menuItem = sender as MenuItem;
            switch (menuItem.Name)
            {
                case "Menu_NewGame":
                    InitGame();
                    break;
             }
        }

内嵌图片到exe中

很多时候图片资源是需要后续动态调整的,而且由于图片比较大,内嵌到exe中会导致exe文件过大
但是对于不需要动态调整,并且图片很小(一堆图片甚至只有几k)的单机小程序来说,单独exe不带资源文件夹是最好用的。
1.先把图片或图片文件夹拖入解决方案下命名空间中
2.把所有图片的属性-生成操作-设置为Resource
如下图
在这里插入图片描述
使用方式:

ImageSource image = new BitmapImage(new Uri("pack://application:,,,/resources/mine.png"));

注意这个路径是绝对路径

窗口大小、图标、大小固定

1.窗口大小动态调整
代码直接设置Width和Height即可
2.窗口左上角的图标设置

this.Icon = new BitmapImage(new Uri("pack://application:,,,/resources/mine.png"));

3.大小固定

<Window ResizeMode="NoResize"></Window>

将字符串复制到剪切板

System.Windows.Clipboard.SetDataObject("https://blog.csdn.net/qq_40543071");

使用默认浏览器打开链接

using System.Diagnostics;

Process proc = new Process();
proc.StartInfo.FileName = "https://go.microsoft.com/fwlink/?LinkId=517009";
proc.Start();

程序所在目录,桌面路径,ApplicationData路径

1.程序所在目录
比如你的exe在D盘Project文件夹下,它会返回D:\Project
注意,结尾不带 \ 你可以自己加一个

System.Environment.CurrentDirectory

2.桌面路径
结尾也不带 \

Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory)

3.ApplicationData路径
运行程序本地数据存储目录之一,要么存这里,要么存exe旁边的文件夹

Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)

因为只是给了主文件夹,最好还是建一个自己程序的文件夹

Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "/Mines_by_Cressfish"

4.创建文件夹
自定义的目录最开始可能不存在,所以新建一个
Directory在System.IO里

if (!Directory.Exists(sPath))
    Directory.CreateDirectory(sPath);// 如果这个路径不存在-创建路径

5.由于我做的扫雷是单个exe,并且很小,所以仍桌面直接玩就行,但是本地存档就不知道放哪
放exe旁边是最好的,方便管理,但是在桌面就不合适了。所以判断一下
如果程序在桌面就放到ApplicationData路径里
默认是放exe旁边了

string strPath = Environment.CurrentDirectory + "/config.txt";
if (Environment.CurrentDirectory == Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory))
{
    string sPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "/Mines_by_Cressfish";
    if (!Directory.Exists(sPath))
        Directory.CreateDirectory(sPath);// 如果这个路径不存在-创建路径
    strPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "/Mines_by_Cressfish/config.txt";
}

ListBox Item切换选中事件

<ListBox SelectionChanged="ListBox_SelectionChanged">
	<ListBoxItem IsSelected="True" x:Name="listItem1">初级</ListBoxItem>
    <ListBoxItem x:Name="listItem2">中级</ListBoxItem>
    <ListBoxItem x:Name="listItem3">高级</ListBoxItem>
</ListBox>

当其中一个Item设置了IsSelected 的时候,在窗口加载的时候会默认选中
1.判断是否有Item被选中了,以及选中后更改背景高亮,获取选中Item的文字

 private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
 {
      foreach (ListBoxItem item in listBox.Items)
      {
          item.Background = Brushes.Transparent;//恢复默认颜色
      }
      if (listBox.SelectedItem != null)
      {
           ListBoxItem listBoxItem = listBox.SelectedItem as ListBoxItem;
           listBoxItem.Background = Brushes.LightSkyBlue;
           if ((string)listBoxItem.Content == "初级")
           {
                ...
           }
      }
 }

按钮鼠标悬浮效果更改,以及指定位置

1.鼠标悬浮效果更改
在这里插入图片描述
默认的效果会使Button上的图片直接被覆盖,看不到底图
在网上找了一个Style解决这个问题

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style x:Key="ChangeButtonIsMouseOver" TargetType="Button">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Border Name="border" BorderThickness="0" BorderBrush="Black" Background="{TemplateBinding Background}">
                        <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Opacity" Value="0.55" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

使用方法:我的是动态生成Button

Style _btnStyle = new ResourceDictionary
{
    Source = new Uri("ChangeButtonIsMouseOver.xaml", UriKind.RelativeOrAbsolute)
}["ChangeButtonIsMouseOver"] as Style;
Button button = new Button(){ Style = _btnStyle };
//这样也行
button.SetValue(StyleProperty, Application.Current.Resources["ChangeButtonIsMouseOver"]);

效果对比一下
在这里插入图片描述
这样就能看到底图是什么了。
2.动态设置Button位置
我本来以为直接设置就可以了,但是比我想象中麻烦
首先是需要把按钮放在Canvas下,Grid不行

 <Canvas x:Name="Canvas_Game" Margin="15,20,15,25"> </Canvas>

动态设置位置的代码
i 是第几行,j是第几列,17是按钮本身大小(17*17)

btn.SetValue(Canvas.LeftProperty, j * 17.0 + 17);
btn.SetValue(Canvas.TopProperty, i * 17.0 + 17);
Canvas_Game.Children.Add(btn);//添加到Canvas里

动态给Button更换图片

这个Url是内嵌的图片路径

BitmapImage bitmapBlank = new BitmapImage();
bitmapBlank.BeginInit();
bitmapBlank.UriSource = new Uri("pack://application:,,,/resources/blank.png");
bitmapBlank.EndInit();
bitmapBlank.Freeze();
ImageBrush _btnBrush = new ImageBrush() { ImageSource = bitmapBlank };
button.Background = _btnBrush;

Button 左键点击,右键点击

事件:PreviewMouseLeftButtonDown、PreviewMouseRightButtonDown
MouseDown可以右键但是左键不行,不知道为什么

private void Btn_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)

sender是点击的Button

XML存读取

存XML

//存
XmlDocument doc = new XmlDocument();
XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", "utf-8", null);
doc.AppendChild(dec);
//创建根节点
XmlElement root = doc.CreateElement("root");
doc.AppendChild(root);
//创建节点-节点可以套节点
XmlElement easy = doc.CreateElement("Easy");
root.AppendChild(easy);// 添加到root节点里

XmlElement time = doc.CreateElement("time");
time.InnerText = "123456"; //<time>123456</time>
time.SetAttribute("name","xxx");//<time name="xxx">123456</time>
//SetAttribute可以有很多个,但是InnerText是唯一的
easy.AppendChild(time);// 添加到easy节点里
//........
doc.Save(strPath);//给他一个路径,比如D:\Mines\config.txt

读XML

XmlDocument doc = new XmlDocument();
//加载要读取的XML
doc.Load(strPath);
//获得根节点
XmlElement books = doc.DocumentElement;
//获得子节点 返回节点的集合。任何一个节点都可以获取其子节点的集合
XmlNodeList xnl = books.ChildNodes;
//foreach循环分析
foreach(XmlNode node in xnl)
{
	if(node.Name == "Easy")
	{
		XmlNodeList easyList = node.ChildNodes;
		foreach(XmlNode easyNode in easyList)
		{
			if(easyNode.Name == "time")
			{
				string strInnerText = easyNode.InnerText;
				string strName = easyNode.Attributes["name"].Value;
				//...
			}
		}
	}
}

像是这样。
基本可以满足需求

子窗口访问 MainWindow

有时候我们需要做窗口之间交互,最简单的办法是MainWindow静态自己并开放出去
也就是单例

public static MainWindow mainWindow;
public MainWindow()
{
    InitializeComponent();
	// 单例指向自己
    mainWindow = this;
}

虽然不安全,但确实是最简单,最方便的方法了。
至于主窗口访问其他窗口。
我是直接在主窗口类里声明子窗口类对象,需要用直接使用就好了。

C#计算百分比

忘了在哪找的了,但是很好用,可以自己更改结果格式,默认是"50%"字符串格式

// 获取百分比
public static string ExecPercent(decimal PassCount, decimal allCount, bool isBaiFenhao = true)
{
	string res = "";
    if (allCount > 0)
    {
    	res = ChinaRound((double)Math.Round(PassCount / allCount * 100, 1), 0).ToString() + (isBaiFenhao ? "%" : "");
    }
    return res;
}
private static double ChinaRound(double value, int decimals)
{
    if (value < 0)
    {
         return Math.Round(value + 5 / Math.Pow(10, decimals + 1), decimals, MidpointRounding.AwayFromZero);
    }
    else
    {
         return Math.Round(value, decimals, MidpointRounding.AwayFromZero);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WPF MVVM架构中,如果要实现点餐历史记录功能,可以使用以下方法: 1. 创建一个数据模型类,用于表示点餐记录的属性,例如订单号、顾客姓名、点餐时间、总金额等。 2. 创建一个继承自ObservableCollection的订单集合,用于保存点餐历史记录。 3. 在ViewModel中,创建一个名为OrderHistory的ObservableCollection属性,用于在View中展示点餐历史记录。 4. 在ViewModel中,创建一个名为AddOrderHistory的方法,用于将新的点餐记录添加到OrderHistory集合中。 5. 在View中,使用ListBox或DataGrid控件来展示OrderHistory集合中的点餐历史记录。 6. 在View中,通过绑定命令的方式,将按钮的点击事件与ViewModel中的AddOrderHistory方法进行绑定,以实现点击按钮时添加点餐记录的功能。 7. 在View中,使用TextBox等控件,通过绑定到ViewModel中的相应属性,来实现输入点餐记录的功能。 8. 可以使用对话框或其他方式,来展示详细的点餐历史记录信息,例如订单详情、菜品清单等。 9. 如果需要对点餐历史记录进行搜索或过滤,可以在ViewModel中添加相应的方法或属性,用于实现这些功能。 通过上述步骤,我们可以在WPF MVVM架构中实现点餐历史记录的功能。在View中展示点餐历史记录,用户可以通过页面上的按钮来添加记录,也可以通过输入框来手动输入记录。同时,我们也提供了搜索、过滤等功能,使得用户可以更方便地管理和查找历史记录。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值