Avalonia(C#) 要使用ViewModels方式指定UI元件(ListBox)資料SOP
Avalonia(C#) 要使用ViewModels方式指定UI元件(ListBox)資料SOP
資料來源: VS2022標準預設官方範例~ MainWindowViewModel
ViewModels 使用步驟:
▲[固定語法(寫在axaml)] xmlns:vm=”using:VPOS_Avalonia.ViewModels”
▲[對應語法(寫在axaml)] x:DataType=”vm:LoginViewModel”
▲[對應語法(寫在axaml)] <Design.DataContext>
▲[對應語法(寫在cs)] DataContext = new LoginViewModel();//建構子函數中資源檔載入[InitializeComponent();]前必須指定ViewModel
[範例程式]
Login.axaml
<Window xmlns="https://github.com/avaloniaui" 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" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" xmlns:local="clr-namespace:VPOS_Avalonia" x:Class="VPOS_Avalonia.Login" xmlns:vm="using:VPOS_Avalonia.ViewModels" x:DataType="vm:LoginViewModel" Title="Login" Loaded="Login_Loaded"> <!-- ViewModels 使用步驟: ▲[固定(axaml)] xmlns:vm="using:VPOS_Avalonia.ViewModels" ▲[對應(axaml)] x:DataType="vm:LoginViewModel" ▲[對應(axaml)] <Design.DataContext> ▲[對應(cs)] DataContext = new LoginViewModel();//建構子函數中資源檔載入[InitializeComponent();]前必須指定ViewModel --> <Design.DataContext> <vm:LoginViewModel/> </Design.DataContext> <Grid x:Name="FullGrid" RowDefinitions ="45,6.4*,0.6*" ColumnDefinitions="*,*" Background="#194a6e" Margin="5,5,5,5"> <local:BaseButton x:Name="Close" Grid.Row="0" Grid.Column="1" TextSize="30" Text="X" TextColor="White" BackgroundColor="#194a6e" BorderColor="#194a6e" Width="45" Height="45" HorizontalAlignment="Right" VerticalAlignment="Top" ExternalClicked="Close_Clicked"/> <Grid x:Name="LeftGrid" Grid.Row="1" Grid.Column="0" Margin="13,10,13,21"> <Border BorderBrush="White" BorderThickness="1" CornerRadius="10" > <ListBox x:Name="lvUser" SelectionMode="Single" ItemsSource="{Binding Items}" Background="White" SelectionChanged="lvUser_ItemSelected"> <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal" Spacing="10" Margin="5"> <Image Source="/Assets/user.png" Width="50" Height="50" Margin="5"/> <TextBlock Text="{Binding user_account}" FontSize="35" VerticalAlignment="Center" Margin="5"/> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Border> </Grid> <Grid x:Name="RightGrid" Grid.Row="1" Grid.Column="1" RowDefinitions ="1*,4*" Margin="13,10,13,21"> <Border Grid.Row="0" BorderBrush="White" BorderThickness="1" CornerRadius="10" Margin="0,0,0,15"> <Grid RowDefinitions ="*,*"> <TextBlock x:Name="labUserName" Grid.Row="0" Text="" FontSize="35" VerticalAlignment="Center" Foreground="White" Margin="20,5"/> <TextBox x:Name="txtPassword" Grid.Row="1" PasswordChar="●" FontSize="40" Background="LightBlue" VerticalContentAlignment="Center" Watermark="Enter password" Margin="20,5" TextChanged ="txtPassword_TextChanged"/> </Grid> </Border> <Border Grid.Row="1" BorderBrush="White" BorderThickness="1" CornerRadius="10" Margin="0,5,0,0"> <Grid RowDefinitions ="*,*,*,*" ColumnDefinitions="*,*,*,*"> <local:BaseButton x:Name="Num01" Grid.Row="0" Grid.Column="0" Margin="10,10,10,10" TextSize="30" Text="1" TextColor="White" BackgroundColor="#194a6e" BorderColor="White" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ExternalClicked="NumberBtn_Clicked"/> <local:BaseButton x:Name="Num02" Grid.Row="0" Grid.Column="1" Margin="10,10,10,10" TextSize="30" Text="2" TextColor="White" BackgroundColor="#194a6e" BorderColor="White" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ExternalClicked="NumberBtn_Clicked"/> <local:BaseButton x:Name="Num03" Grid.Row="0" Grid.Column="2" Margin="10,10,10,10" TextSize="30" Text="3" TextColor="White" BackgroundColor="#194a6e" BorderColor="White" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ExternalClicked="NumberBtn_Clicked"/> <Grid Grid.Row="0" Grid.Column="3" Grid.RowSpan="3" RowDefinitions ="*,*"> <local:BaseButton x:Name="BtnC" Grid.Row="0" Margin="10,10,10,10" TextSize="30" Text="C" TextColor="White" BackgroundColor="#194a6e" BorderColor="White" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ExternalClicked="BtnClear_Clicked"/> <local:BaseButton x:Name="BtnDel" Grid.Row="1" Margin="10,10,10,10" TextSize="30" Text="Del" TextColor="White" BackgroundColor="#194a6e" BorderColor="White" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ExternalClicked="BtnDelete_Clicked"/> </Grid> <local:BaseButton x:Name="Num04" Grid.Row="1" Grid.Column="0" Margin="10,10,10,10" TextSize="30" Text="4" TextColor="White" BackgroundColor="#194a6e" BorderColor="White" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ExternalClicked="NumberBtn_Clicked"/> <local:BaseButton x:Name="Num05" Grid.Row="1" Grid.Column="1" Margin="10,10,10,10" TextSize="30" Text="5" TextColor="White" BackgroundColor="#194a6e" BorderColor="White" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ExternalClicked="NumberBtn_Clicked"/> <local:BaseButton x:Name="Num06" Grid.Row="1" Grid.Column="2" Margin="10,10,10,10" TextSize="30" Text="6" TextColor="White" BackgroundColor="#194a6e" BorderColor="White" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ExternalClicked="NumberBtn_Clicked"/> <local:BaseButton x:Name="Num07" Grid.Row="2" Grid.Column="0" Margin="10,10,10,10" TextSize="30" Text="7" TextColor="White" BackgroundColor="#194a6e" BorderColor="White" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ExternalClicked="NumberBtn_Clicked"/> <local:BaseButton x:Name="Num08" Grid.Row="2" Grid.Column="1" Margin="10,10,10,10" TextSize="30" Text="8" TextColor="White" BackgroundColor="#194a6e" BorderColor="White" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ExternalClicked="NumberBtn_Clicked"/> <local:BaseButton x:Name="Num09" Grid.Row="2" Grid.Column="2" Margin="10,10,10,10" TextSize="30" Text="9" TextColor="White" BackgroundColor="#194a6e" BorderColor="White" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ExternalClicked="NumberBtn_Clicked"/> <Grid Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="4" ColumnDefinitions ="*,*"> <local:BaseButton x:Name="Num00" Grid.Column="0" Margin="10,10,10,10" TextSize="30" Text="0" TextColor="White" BackgroundColor="#194a6e" BorderColor="White" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ExternalClicked="NumberBtn_Clicked"/> <local:BaseButton x:Name="BtnLogin" Grid.Column="1" Margin="10,10,10,10" TextSize="30" Text="登入" TextColor="White" BackgroundColor="#194a6e" BorderColor="White" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ExternalClicked="BtnEnter_Clicked"/> </Grid> </Grid> </Border> </Grid> <Grid x:Name="EndGrid" Grid.Row="2" Grid.Column="0" Margin="20,5,20,15" ColumnDefinitions ="*,*" > <local:ImageButton x:Name="ResetBtn" Grid.Row="0" Grid.Column="0" TextSize="30" Text="重新開機" TextColor="White" BackgroundColor="#194a6e" BorderColor="White" ImageSource="/Assets/reset.png" Width="200" VerticalAlignment="Stretch" ExternalClicked="ResetBtn_Clicked"/> <local:ImageButton x:Name="ShutdownBtn" Grid.Row="0" Grid.Column="1" TextSize="30" Text="關 機" TextColor="White" BackgroundColor="#194a6e" BorderColor="White" ImageSource="/Assets/shutdown.png" Width="200" VerticalAlignment="Stretch" ExternalClicked="ShutdownBtn_Clicked"/> </Grid> </Grid> </Window>
LoginViewModel.cs
using System.Collections.ObjectModel; namespace VPOS_Avalonia.ViewModels { public class LoginItem { public string role_sid { get; set; } public string user_account { get; set; } public string user_pwd { get; set; } public string employee_no { get; set; } public string SID { get; set; } } public partial class LoginViewModel : ViewModelBase { #pragma warning disable CA1822 // Mark members as static public ObservableCollection<LoginItem> Items { get; set; }= new ObservableCollection<LoginItem>(); public string Text => "Welcome to Avalonia!"; #pragma warning restore CA1822 // Mark members as static } }
Login.axaml.cs
using Avalonia; using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Interactivity; using Avalonia.Markup.Xaml; using Avalonia.Media; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Data; using System.Diagnostics; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using VPOS; using VPOS_Avalonia.Views; using VPOS_Avalonia.ViewModels; namespace VPOS_Avalonia; public partial class Login : Window { public static bool m_blnCloseApp = true; public String m_StrPIN = ""; public String m_Strrole_sid = ""; public Login() { DataContext = new LoginViewModel();//資源檔載入前必須指定ViewModel ExternalPopup.login = this; this.WindowState = WindowState.FullScreen; //隱藏工具列 this.ExtendClientAreaToDecorationsHint = true; this.ExtendClientAreaTitleBarHeightHint = -1; this.SystemDecorations = SystemDecorations.None; //---隱藏工具列 this.Background = new SolidColorBrush(Color.Parse("#194a6e"));//設定背景色 this.BorderBrush = Brushes.Blue;//設定藍色邊框 this.BorderThickness = new Thickness(2);//設定邊框寬度 InitializeComponent(); //--- //資源檔載入的後續調整 if (MainWindow.m_dblScreenWidth != 1920) { txtPassword.FontSize = txtPassword.FontSize * 2 / 3; } //---資源檔載入的後續調整 } private void Login_Loaded(object sender, RoutedEventArgs e) { LogFile.Write("LoginPage Start"); if (SQLDataTableModel.user_dataLoad()) { LogFile.Write("Have login accounts"); for (int i = 0; i < SQLDataTableModel.m_user_dataDataTable.Rows.Count; i++) { LoginItem loginItemBuf = new LoginItem(); loginItemBuf.role_sid = SQLDataTableModel.m_user_dataDataTable.Rows[i]["role_sid"].ToString(); loginItemBuf.user_account = SQLDataTableModel.m_user_dataDataTable.Rows[i]["user_account"].ToString(); loginItemBuf.user_pwd = SQLDataTableModel.m_user_dataDataTable.Rows[i]["user_pwd"].ToString(); loginItemBuf.employee_no = SQLDataTableModel.m_user_dataDataTable.Rows[i]["employee_no"].ToString(); loginItemBuf.SID = SQLDataTableModel.m_user_dataDataTable.Rows[i]["SID"].ToString(); ((LoginViewModel)(this.DataContext)).Items.Add(loginItemBuf); } if(SQLDataTableModel.m_user_dataDataTable.Rows.Count>0) { lvUser.SelectedIndex = 0; } } } private async void ResetBtn_Clicked(object sender, RoutedEventArgs e) { await ExternalPopup.QuesMessageBox(2, "確定要執行重新開機動作?"); if (QuesMessageBox.m_blnResult) { LogFile.Write("Reset PC"); Process.Start("shutdown.exe", "/r /t 0");//重啟 ~ https://blog.csdn.net/xinbadar/article/details/78819565 } } private async void ShutdownBtn_Clicked(object sender, RoutedEventArgs e) { await ExternalPopup.QuesMessageBox(2, "確定要執行關機動作?"); if (QuesMessageBox.m_blnResult) { LogFile.Write("Shutdown PC"); Process.Start("shutdown.exe", "/s /t 0");//關機 ~ https://blog.csdn.net/xinbadar/article/details/78819565 } } private void Close_Clicked(object sender, RoutedEventArgs e) { this.Close(); } private void ShowMainUI() { if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { MainWindow MainUI = new MainWindow(); m_blnCloseApp = false; desktop.MainWindow = MainUI; MainUI.Show(); this.Close(); } } private void txtPassword_TextChanged(object sender, TextChangedEventArgs e) { txtPassword.Text = Regex.Replace(txtPassword.Text, "[^0-9]", "");//限制登入密碼只能是數字 } private void NumberBtn_Clicked(object sender, RoutedEventArgs e) { txtPassword.Text += ((BaseButton)(sender)).Text; txtPassword.Focus(); } private void BtnDelete_Clicked(object sender, RoutedEventArgs e) { if (txtPassword.Text.Length > 0) { txtPassword.Text = txtPassword.Text.Substring(0, txtPassword.Text.Length - 1); } txtPassword.Focus(); } private void BtnClear_Clicked(object sender, RoutedEventArgs e) { txtPassword.Text = ""; txtPassword.Focus(); } private async void BtnEnter_Clicked(object sender, RoutedEventArgs e) { String StrPIN = ""; if ((txtPassword.Text != null) && (txtPassword.Text.Length > 0)) { try { SHA256 sha256 = new SHA256CryptoServiceProvider();//建立一個SHA256 byte[] source = Encoding.Default.GetBytes(txtPassword.Text);//將字串轉為Byte[] byte[] crypto = sha256.ComputeHash(source); for (int i = 0; i < crypto.Length; i++)//BYTE陣列資料 變成 16進制 { StrPIN += Convert.ToString(crypto[i], 16).PadLeft(2, '0'); } } catch (Exception ex) { StrPIN = ""; } } if (m_StrPIN == StrPIN) { //--- //載入func_main資料表的資訊到購物車UI的對應成員變數中 MainWindow.m_funcMain.Clear(); String SQL = String.Format("SELECT fm.SID AS SID,fm.func_name AS Name,IFNULL(rf.role_sid,0) AS Eenabe FROM func_main AS fm LEFT JOIN role_func AS rf ON (fm.SID=rf.func_sid) AND (rf.role_sid='{0}')", m_Strrole_sid); DataTable dt = SQLDataTableModel.GetDataTable(SQL); if ((dt != null) && (dt.Rows.Count > 0)) { for (int i = 0; i < dt.Rows.Count; i++) { MainWindow.m_funcMain.Add(new func_mainData(dt.Rows[i]["SID"].ToString(), dt.Rows[i]["Name"].ToString(), (dt.Rows[i]["Eenabe"].ToString() == "0") ? false : true)); } } //---載入func_main資料表的資訊到購物車UI的對應成員變數中 POS_INVAPI.m_blnAutoCheck = (App.m_intNetworkLevel > 0) ? true : false;//是否自動偵測 POS_ECMAPI.m_blnRunInit = true;//登入成功就執行悠遊卡設備初始化 NCCCAPI.m_blnRunInit = true;//聯信卡機初始偵測 MainWindow.m_blnShowDailyQuestion = true;//自動營業關帳提示訊息旗標 LogFile.Write("Sign in suceesfully"); LogFile.Write("LoginPage End"); ShowMainUI(); } else { String StrMsg = ""; if ((txtPassword.Text != null) && (txtPassword.Text.Length > 0)) { StrMsg = "使用者密碼驗證失敗"; } else { StrMsg = "請輸入密碼"; } LogFile.Write("Login failed"); await ExternalPopup.MessageBox(2, StrMsg); } } private void lvUser_ItemSelected(object sender, SelectionChangedEventArgs e) { if (lvUser.SelectedItem !=null) { LogFile.Write("Switch login account"); labUserName.Text = ((LoginItem)lvUser.SelectedItem).user_account;//await this.ShowPopupAsync(new MessageBox(selectedItem.Text)); m_Strrole_sid = ((LoginItem)lvUser.SelectedItem).role_sid; m_StrPIN = ((LoginItem)lvUser.SelectedItem).user_pwd; MainWindow.m_StrEmployeeNo = ((LoginItem)lvUser.SelectedItem).employee_no; MainWindow.m_StrUserAccount = ((LoginItem)lvUser.SelectedItem).user_account; MainWindow.m_StrUserSID = ((LoginItem)lvUser.SelectedItem).SID; //lvUser.SelectedItem = null;// 清除選擇狀態 } } }