C# WINDOWS MAUI專案 建立自訂彈出對話合視窗(Custom PopupPage/Dialog)
C# WINDOWS MAUI專案 建立自訂彈出對話合視窗(Custom PopupPage/Dialog)
資料來源: https://www.youtube.com/watch?v=yM7opXlu-MU [Showing Popups in .NET MAUI with .NET MAUI Community Toolkit]
GITHUB:
https://github.com/jash-git/MAUI_WinAPI_Object_test/tree/main/Code/04
https://github.com/jash-git/MAUI_WinAPI_Object_test/tree/main/Code/13 [指定顯示在0,0位置 ~ (HorizontalOptions=”Start” VerticalOptions=”Start”)]
PopupPage.xaml Code:
<?xml version="1.0" encoding="utf-8" ?>
<mct:Popup xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:mct="clr-namespace:CommunityToolkit.Maui.Views;assembly=CommunityToolkit.Maui"
x:Class="MAUI_WinAPI_Object_test.PopupPage"
CanBeDismissedByTappingOutsideOfPopup="False">
<VerticalStackLayout BackgroundColor="Blue">
<Label
Text="Welcome to .NET MAUI!"
VerticalOptions="Center"
HorizontalOptions="Center" />
<Button
x:Name="CloseBtn"
Text="Close App"
Clicked="OnClosed"
HorizontalOptions="Center" ClassId="" />
</VerticalStackLayout>
</mct:Popup>
PopupPage.xaml.cs Code:
using CommunityToolkit.Maui.Views;
namespace MAUI_WinAPI_Object_test;
public partial class PopupPage: Popup // : ContentPage
{
public PopupPage()
{
InitializeComponent();
//Size = new Size(500, 500);//設定UI大小
}
private void OnClosed(object sender, EventArgs e)
{
Close();
}
}
MainPage.xaml Code:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MAUI_WinAPI_Object_test.MainPage">
<ScrollView>
<VerticalStackLayout
Spacing="25"
Padding="30,0"
VerticalOptions="Center">
<Image
Source="dotnet_bot.png"
SemanticProperties.Description="Cute dot net bot waving hi to you!"
HeightRequest="200"
HorizontalOptions="Center" />
<Label
x:Name="labtime"
Text="Hello, World!"
SemanticProperties.HeadingLevel="Level1"
FontSize="32"
HorizontalOptions="Center" />
<Label
Text="Welcome to .NET Multi-platform App UI"
SemanticProperties.HeadingLevel="Level2"
SemanticProperties.Description="Welcome to dot net Multi platform App U I"
FontSize="18"
HorizontalOptions="Center" />
<Button
x:Name="CounterBtn"
Text="Click me"
SemanticProperties.Hint="Counts the number of times you click"
Clicked="OnCounterClicked"
HorizontalOptions="Center" />
<Button
x:Name="PopupBtn"
Text="Show Popup"
SemanticProperties.Hint="Counts the number of times you click"
Clicked="OnPopupClicked"
HorizontalOptions="Center" />
<Button
x:Name="CloseBtn"
Text="Close App"
Clicked="OnClosed"
HorizontalOptions="Center" ClassId="" />
</VerticalStackLayout>
</ScrollView>
</ContentPage>
MainPage.xaml.cs Code
//using Android.App;
using CommunityToolkit.Maui.Views;
using Jint;
using Microsoft.Maui.Controls;
using System.Data;
using System.Data.SQLite;
using System.IO.Ports;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace MAUI_WinAPI_Object_test;
public partial class MainPage : ContentPage
{
int count = 0;
public IDispatcherTimer timmer { get; set; }
public Thread thread;
public bool blnStop = false;
public MainPage()
{
InitializeComponent();
/*
//---
//Timer Mode
//https://learn.microsoft.com/en-us/answers/questions/1207012/how-to-stop-device-starttimer
timmer = Application.Current.Dispatcher.CreateTimer();
timmer.Interval = new TimeSpan(0, 0, 0, 0, 100);//天/時/分/秒/毫秒
timmer.Tick += Timmer_Tick;
timmer.IsRepeating = true;//the timer will keep recurring, you can set false
timmer.Start();
//---Timer Mode
//*/
// 在新執行緒中執行工作
thread = new Thread(ThreadFun);
thread.Start();
}
private void Timmer_Tick(object sender, EventArgs e)
{
labtime.Text = DateTime.Now.ToString("HH:mm:ss");
}
private void ThreadFun()
{
// 模擬一些耗時的工作
do
{
// 更新使用者介面 (UI) 元素
Device.BeginInvokeOnMainThread(() =>
{
// 在這裡更新 UI 控制項
labtime.Text = DateTime.Now.ToString("HH:mm:ss");
});
Thread.Sleep(1000);
} while (!blnStop);
}
private async void OnCounterClicked(object sender, EventArgs e)
{
count++;
if (count == 1)
CounterBtn.Text = $"Clicked {count} time";
else
CounterBtn.Text = $"Clicked {count} times";
await DisplayAlert("Alert", $"路徑:{AppDomain.CurrentDomain.BaseDirectory}", "OK");//await
DataTable dtbuf = GetDataTable("vpos.db", "SELECT * FROM class_data");
//---
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);//載入.net Big5編解碼函數庫(System.Text.Encoding.CodePages)
StreamReader sr = new StreamReader(@"C:\Users\devel\Desktop\Input.json");
string StrInput = sr.ReadLine();
sr.Close();// 關閉串流
ESCPOS_Receipt_RS232Print(StrInput);
//---
}
private void OnPopupClicked(object sender, EventArgs e)
{
this.ShowPopup(new PopupPage());
}
public static SerialPort m_port = new SerialPort();
public static void CommDataReceived(Object sender, SerialDataReceivedEventArgs e)
{
//https://www.cnblogs.com/xinaixia/p/6216745.html
try
{
//Comm.BytesToRead中为要读入的字节长度
int len = m_port.BytesToRead;
Byte[] readBuffer = new Byte[len];
m_port.Read(readBuffer, 0, len); //将数据读入缓存
//处理readBuffer中的数据,自定义处理过程
}
catch (Exception ex)
{
}
}
static void ESCPOS_Receipt_RS232Print(String StrInput = "")//收據
{
Console.WriteLine("Init Jint...");
var engine = new Engine();
engine.Execute(System.IO.File.ReadAllText(AppDomain.CurrentDomain.BaseDirectory + "Script" +
Path.DirectorySeparatorChar + "CommonFun.js"));
engine.Execute(System.IO.File.ReadAllText(AppDomain.CurrentDomain.BaseDirectory + "Script" +
Path.DirectorySeparatorChar + "QrCode_57mm.js"));
engine.SetValue("input", StrInput);
Console.WriteLine("Create ESC_Command...");
String StrFunName = "Main()";
var Jsonresult = engine.Execute(StrFunName).GetCompletionValue();
ESCPOS_OrderNew ESCPOSCommand = new ESCPOS_OrderNew();
ESCPOSCommand = JsonSerializer.Deserialize<ESCPOS_OrderNew>(Jsonresult.AsString());
Console.WriteLine("C# Modified ESC_Command Start");
if ((ESCPOSCommand != null) && (ESCPOSCommand.state_code == 0) && (ESCPOSCommand.value != null) && (ESCPOSCommand.value.Count > 0))
{
for (int i = 0; i < ESCPOSCommand.value.Count; i++)
{
ESCPOSCommand.value[i] = UnescapeUnicode(ESCPOSCommand.value[i]);
}
}
Console.WriteLine("C# Modified ESC_Command End");
string[] m_comports;//= SerialPort.GetPortNames();
m_comports = SerialPort.GetPortNames();
if ((m_comports.Length > 0) && (!m_port.IsOpen))
{
m_port.PortName = m_comports[0];
//m_port.BaudRate = 115200;//RP-700 ;
m_port.BaudRate = 19200;//PDC325
m_port.DataBits = 8;
m_port.StopBits = StopBits.One;
m_port.Parity = Parity.None;
m_port.ReadTimeout = 1;
m_port.ReadTimeout = 3000; //单位毫秒
m_port.WriteTimeout = 3000; //单位毫秒
//串口控件成员变量,字面意思为接收字节阀值,
//串口对象在收到这样长度的数据之后会触发事件处理函数
//一般都设为1
m_port.ReceivedBytesThreshold = 1;
m_port.DataReceived += new SerialDataReceivedEventHandler(CommDataReceived); //设置数据接收事件(监听)
m_port.Open();
Console.WriteLine("ESC_Command to Printer Start");
if ((ESCPOSCommand != null) && (ESCPOSCommand.value != null))
{
for (int i = 0; i < ESCPOSCommand.value.Count; i++)
{
//會亂碼 byte[] bytes = Encoding.UTF8.GetBytes(ESCPOSCommand.value[i]);
//會亂碼 byte[] bytes = Encoding.Default.GetBytes(ESCPOSCommand.value[i]);
//會亂碼 byte[] bytes = Encoding.ASCII.GetBytes(ESCPOSCommand.value[i]);
//會亂碼 byte[] bytes = Encoding.Latin1.GetBytes(ESCPOSCommand.value[i]);
//byte[] bytes = Encoding.GetEncoding("big5").GetBytes(ESCPOSCommand.value[i]);
m_port.Write(Encoding.GetEncoding("big5").GetBytes(ESCPOSCommand.value[i]), 0, Encoding.GetEncoding("big5").GetBytes(ESCPOSCommand.value[i]).Length);
//m_port.Write(bytes, 0, bytes.Length);
}
}
//*/
Console.WriteLine("ESC_Command to Printer End");
}
else
{
m_port.Close();
}
}
private void OnClosed(object sender, EventArgs e)
{
if(timmer!=null)
{
timmer.Stop();
}
if(thread!=null)
{
blnStop = true;
thread = null;
}
// Close the active window
//https://learn.microsoft.com/en-us/dotnet/maui/fundamentals/windows
Application.Current.CloseWindow(GetParentWindow());
}
public static string UnescapeUnicode(string str) // 将unicode转义序列(\uxxxx)解码为字符串
{
//GOOGLE: C# \uXXXX
//https://www.cnblogs.com/netlog/p/15911016.html C#字符串Unicode转义序列编解码
//https://docs.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.regex.unescape?view=net-6.0
//https://docs.microsoft.com/zh-tw/dotnet/api/system.text.regularexpressions.regex.unescape?view=net-6.0
return (System.Text.RegularExpressions.Regex.Unescape(str));
}
public static SQLiteConnection OpenConn(string Database)//資料庫連線程式
{
string cnstr = String.Format("Data Source={0};Version=3;", Database);
SQLiteConnection icn = new SQLiteConnection();
icn.ConnectionString = cnstr;
if (icn.State == ConnectionState.Open) { icn.Close(); icn = null; /*GC.Collect();*/ }
icn.Open();
return icn;
}
public static DataTable GetDataTable(string Database, string SQLiteString)//讀取資料程式
{
DataTable myDataTable = new DataTable(Database);
try
{
SQLiteConnection icn = OpenConn(Database);
SQLiteDataAdapter da = new SQLiteDataAdapter(SQLiteString, icn);
DataSet ds = new DataSet();
ds.Clear();
da.Fill(ds);
myDataTable = ds.Tables[0];
da.Dispose();
ds.Dispose();
da = null;
ds = null;
if (icn.State == ConnectionState.Open) { icn.Close(); icn = null; /*GC.Collect();*/ }
if (true)
{
String StrLog = String.Format("{0}: {1};{2}", "sync_GetDataTable", SQLiteString, "success");
}
}
catch (Exception ex)
{
if (true)
{
String StrLog = String.Format("{0}: {1};{2}", "sync_GetDataTable", SQLiteString, ex.ToString());
}
}
return myDataTable;
}
}
public class ESCPOS_OrderNew
{
public int state_code { get; set; }
public List<string> value { get; set; }
}
MauiProgram.cs
//---
//.net MAUI how to maximize application on startup
//https://stackoverflow.com/questions/72128525/net-maui-how-to-maximize-application-on-startup
using Microsoft.Maui.LifecycleEvents;
using CommunityToolkit.Maui;
#if WINDOWS
using Microsoft.UI;
using Microsoft.UI.Windowing;
using Windows.Graphics;
#endif
//---.net MAUI how to maximize application on startup
namespace MAUI_WinAPI_Object_test;
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.UseMauiCommunityToolkit()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
});
//---
//.net MAUI how to maximize application on startup
https://stackoverflow.com/questions/72128525/net-maui-how-to-maximize-application-on-startup
#if WINDOWS
builder.ConfigureLifecycleEvents(events =>
{
events.AddWindows(wndLifeCycleBuilder =>
{
wndLifeCycleBuilder.OnWindowCreated(window =>
{
IntPtr nativeWindowHandle = WinRT.Interop.WindowNative.GetWindowHandle(window);
WindowId win32WindowsId = Win32Interop.GetWindowIdFromWindow(nativeWindowHandle);
AppWindow winuiAppWindow = AppWindow.GetFromWindowId(win32WindowsId);
if(winuiAppWindow.Presenter is OverlappedPresenter p)
{
p.Maximize();
}
//---
//[Windows] How to completely hide the TitleBar?
//https://github.com/dotnet/maui/issues/15142
window.ExtendsContentIntoTitleBar = false;
switch (winuiAppWindow.Presenter)
{
case Microsoft.UI.Windowing.OverlappedPresenter overlappedPresenter:
overlappedPresenter.SetBorderAndTitleBar(false, false);
overlappedPresenter.Maximize();
break;
}
//---[Windows] How to completely hide the TitleBar?
});
});
});
#endif
//---.net MAUI how to maximize application on startup
return builder.Build();
}
}
2 thoughts on “C# WINDOWS MAUI專案 建立自訂彈出對話合視窗(Custom PopupPage/Dialog)”
MAUI Popups | MAUI Community Toolkit
範例程式: https://github.com/Skynet-Demos/MauiPopups
影片 收藏
Highly Customizable Popups for .NET MAUI with Mopups