添加电话应用绑定页面

This commit is contained in:
wenyongda 2025-06-19 17:10:13 +08:00
parent de0a0e3e78
commit 633963be44
6 changed files with 393 additions and 0 deletions

View File

@ -22,6 +22,7 @@
<NavigationView.MenuItems> <NavigationView.MenuItems>
<NavigationViewItem Tag="HomePage" Icon="Home" Content="主页" /> <NavigationViewItem Tag="HomePage" Icon="Home" Content="主页" />
<NavigationViewItem Tag="PhoneAppBinderPage" Icon="PhoneBook" Content="电话应用程序绑定" />
<NavigationViewItem Tag="NotePage" Icon="Bookmarks" Content="笔记" /> <NavigationViewItem Tag="NotePage" Icon="Bookmarks" Content="笔记" />
<NavigationViewItem Tag="FileUploadPage" Icon="Upload" Content="文件上传"></NavigationViewItem> <NavigationViewItem Tag="FileUploadPage" Icon="Upload" Content="文件上传"></NavigationViewItem>
<NavigationViewItemSeparator /> <NavigationViewItemSeparator />

View File

@ -52,6 +52,9 @@ namespace WinUINotes
case "FileUploadPage": case "FileUploadPage":
ContentFrame.Navigate(typeof(FileUploadPage)); ContentFrame.Navigate(typeof(FileUploadPage));
break; break;
case "PhoneAppBinderPage":
ContentFrame.Navigate(typeof(PhoneAppBinderPage));
break;
// 可以添加更多 case 来处理其他导航项 // 可以添加更多 case 来处理其他导航项
} }
} }

View File

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WinUINotes.Model
{
public class PhoneAppItem
{
public string AppName { get; set; }
public List<string> AppUrls { get; set; }
// 这个属性用于在ListView中显示多个网站
public string AppUrlsDisplayString
{
get => AppUrls != null && AppUrls.Count > 0 ? string.Join(", ", AppUrls) : "无网站";
}
}
}

View File

@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<Page
x:Class="WinUINotes.PhoneAppBinderPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:WinUINotes"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:model="using:WinUINotes.Model"
mc:Ignorable="d">
<Grid Padding="20">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="2*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0" Margin="0,0,20,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="已保存项目" FontSize="18" FontWeight="Bold" Margin="0,0,0,10"/>
<Button Grid.Row="1" Content="新增项目" Click="AddNewProjectButton_Click" HorizontalAlignment="Left" Margin="0,0,0,5"/>
<TextBox x:Name="FilterTextBox" Grid.Row="2" PlaceholderText="此输入框暂时不提供过滤功能" Margin="0,5,0,10"/>
<ListView x:Name="ProjectListView" Grid.Row="3" ItemsSource="{x:Bind PhoneAppItems}"
SelectionMode="Single" ShowsScrollingPlaceholders="True"
BorderBrush="{ThemeResource SystemControlForegroundBaseMediumBrush}" BorderThickness="1"
Margin="0,0,0,10"
SelectionChanged="ProjectListView_SelectionChanged">
<ListView.ItemTemplate>
<DataTemplate x:DataType="model:PhoneAppItem">
<StackPanel Margin="0,5">
<TextBlock FontWeight="SemiBold" FontSize="14">
<Run Text="应用程序名称: "/>
<Run Text="{x:Bind AppName}"/>
</TextBlock>
<TextBlock FontSize="12">
<Run Text="关联网站: "/>
<Run Text="{x:Bind AppUrlsDisplayString}"/>
</TextBlock>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
<StackPanel Grid.Column="1" Padding="20" BorderBrush="{ThemeResource SystemControlForegroundBaseMediumBrush}" BorderThickness="1">
<TextBlock Text="应用程序名称:" FontSize="16" FontWeight="SemiBold" Margin="0,0,0,5"/>
<TextBox x:Name="AppNameInputTextBox" PlaceholderText="请输入应用程序名称" HorizontalAlignment="Stretch" Margin="0,0,0,10" IsReadOnly="True" />
<StackPanel Orientation="Horizontal" Margin="0,0,0,10">
<TextBlock Text="网站列表:" FontSize="16" FontWeight="SemiBold" VerticalAlignment="Center"/>
<Button Content="添加网站" Click="AddWebsiteButton_Click" Margin="10,0,0,0" IsEnabled="False"/>
</StackPanel>
<ScrollViewer VerticalScrollMode="Auto" VerticalScrollBarVisibility="Auto" Height="Auto" MaxHeight="200" Margin="0,0,0,20">
<StackPanel x:Name="WebsitesStackPanel" Spacing="10"/>
</ScrollViewer>
<StackPanel Orientation="Horizontal">
<Button x:Name="SaveProjectButton" Content="保存项目" Click="SaveProjectButton_Click" HorizontalAlignment="Stretch" Margin="0, 0, 5, 0" />
<Button x:Name="EditProjectButton" Content="编辑项目" Click="EditProjectButton_Click" HorizontalAlignment="Stretch" />
</StackPanel>
</StackPanel>
</Grid>
</Page>

View File

@ -0,0 +1,288 @@
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Data;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml.Navigation;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using WinUINotes.Model;
// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.
namespace WinUINotes;
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class PhoneAppBinderPage : Page
{
private int _websiteCounter = 0; // 用于给每个网站输入框一个唯一的标识
private PhoneAppItem _selectedPhoneAppItem; // 存储当前在ListView中选中的项目
// 声明一个 ObservableCollection 来存储项目数据,并绑定到 ListView
public ObservableCollection<PhoneAppItem> PhoneAppItems { get; set; } = [];
public PhoneAppBinderPage()
{
InitializeComponent();
this.Loaded += PhoneAppBinderPage_Loaded;
}
private void PhoneAppBinderPage_Loaded(object sender, RoutedEventArgs e)
{
// 初始添加一个网站输入框
AddWebsiteInputControl();
SetInputAreaReadOnly(true); // 页面加载时默认只读
// 可以添加一些示例数据
PhoneAppItems.Add(new PhoneAppItem { AppName = "微信", AppUrls = new List<string> { "https://wechat.com" } });
PhoneAppItems.Add(new PhoneAppItem { AppName = "支付宝", AppUrls = new List<string> { "https://alipay.com" } });
PhoneAppItems.Add(new PhoneAppItem { AppName = "抖音", AppUrls = new List<string> { "https://douyin.com", "https://douyin.net" } });
}
private void AddWebsiteButton_Click(object sender, RoutedEventArgs e)
{
AddWebsiteInputControl();
}
private void AddWebsiteInputControl(string initialUrl= "", bool isReadOnly = false)
{
_websiteCounter++;
// 创建一个包含TextBox和Button的StackPanel
StackPanel websiteEntryPanel = new StackPanel
{
Orientation = Orientation.Horizontal,
Spacing = 10,
Tag = _websiteCounter, // 用于删除时识别
HorizontalAlignment = HorizontalAlignment.Left
};
TextBox websiteTextBox = new TextBox
{
PlaceholderText = $"请输入网站URL ({_websiteCounter})",
Width = 400,
// 可以添加名称便于后续获取数据但Tag更方便定位
// Name = $"WebsiteTextBox_{_websiteCounter}"
Text = initialUrl, // 设置初始值
IsReadOnly = isReadOnly // 控制只读状态
};
Button deleteButton = new Button
{
Content = "删除",
Background = new SolidColorBrush(Microsoft.UI.Colors.Red), // 设置删除按钮背景色
Foreground = new SolidColorBrush(Microsoft.UI.Colors.White), // 设置文字颜色
Tag = _websiteCounter, // 用于删除时识别
Margin = new Thickness(5, 0, 0, 0) // 添加一些左边距
};
deleteButton.Click += DeleteWebsiteButton_Click;
deleteButton.IsEnabled = !isReadOnly; // 只读时禁用删除按钮
websiteEntryPanel.Children.Add(websiteTextBox);
websiteEntryPanel.Children.Add(deleteButton);
WebsitesStackPanel.Children.Add(websiteEntryPanel);
}
private void DeleteWebsiteButton_Click(object sender, RoutedEventArgs e)
{
Button deleteButton = sender as Button;
if (deleteButton != null)
{
int tagToRemove = (int)deleteButton.Tag;
// 找到对应的StackPanel并移除
UIElement panelToRemove = WebsitesStackPanel.Children
.FirstOrDefault(child => child is StackPanel sp && (int)sp.Tag == tagToRemove);
if (panelToRemove != null)
{
WebsitesStackPanel.Children.Remove(panelToRemove);
}
}
}
private void SaveProjectButton_Click(object sender, RoutedEventArgs e)
{
string appName = AppNameInputTextBox.Text.Trim();
List<string> appUrls = new List<string>();
foreach (UIElement child in WebsitesStackPanel.Children)
{
if (child is StackPanel websiteEntryPanel)
{
// 假设第一个子元素是TextBox
if (websiteEntryPanel.Children.FirstOrDefault() is TextBox websiteTextBox)
{
if (!string.IsNullOrWhiteSpace(websiteTextBox.Text))
{
appUrls.Add(websiteTextBox.Text);
}
}
}
}
// 在这里您可以处理收集到的数据
// 例如显示在消息框中保存到文件发送到API等
// 检查应用程序名称是否为空
if (string.IsNullOrWhiteSpace(appName))
{
ShowMessageDialog("错误", "应用程序名称不能为空!");
return;
}
if(_selectedPhoneAppItem == null) // 新增项目
{
PhoneAppItem newAppItem = new PhoneAppItem
{
AppName = appName,
AppUrls = appUrls
};
PhoneAppItems.Add(newAppItem);
ShowMessageDialog("成功", $"项目 '{appName}' 已添加到列表。");
}
else // 更新现有项目
{
_selectedPhoneAppItem.AppName = appName;
_selectedPhoneAppItem.AppUrls = appUrls;
// 强制ListView更新Item因为PhoneAppItem本身没有实现INotifyPropertyChanged
// 这里我们通过移除再添加来强制更新UI或者更优雅的做法是PhoneAppItem实现INotifyPropertyChanged
int index = PhoneAppItems.IndexOf(_selectedPhoneAppItem);
if (index != -1)
{
PhoneAppItems.RemoveAt(index);
PhoneAppItems.Insert(index, _selectedPhoneAppItem);
}
ShowMessageDialog("成功", $"项目 '{appName}' 已更新。");
}
ClearInputArea(); // 清空输入区域
ProjectListView.SelectedItem = null; // 取消ListView选中状态
SetInputAreaReadOnly(true); // 保存后默认只读
}
private void AddNewProjectButton_Click(object sender, RoutedEventArgs e)
{
// 清空右侧输入区域,准备输入新项目
ClearInputArea();
ProjectListView.SelectedItem = null; // 取消ListView选中状态
_selectedPhoneAppItem = null; // 重置选中项
SetInputAreaReadOnly(false); // 启用编辑模式
AppNameInputTextBox.Focus(FocusState.Programmatic); // 让应用名称输入框获得焦点
}
// 编辑项目按钮点击事件
private void EditProjectButton_Click(object sender, RoutedEventArgs e)
{
if (_selectedPhoneAppItem == null)
{
ShowMessageDialog("提示", "请先从列表中选择一个项目进行编辑。");
return;
}
SetInputAreaReadOnly(false); // 解除只读状态,允许编辑
AppNameInputTextBox.Focus(FocusState.Programmatic); // 让应用名称输入框获得焦点
}
// ListView 选择项改变事件
private void ProjectListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
_selectedPhoneAppItem = ProjectListView.SelectedItem as PhoneAppItem;
if (_selectedPhoneAppItem != null)
{
// 填充右侧输入框
AppNameInputTextBox.Text = _selectedPhoneAppItem.AppName;
WebsitesStackPanel.Children.Clear();
_websiteCounter = 0; // 重置计数器
foreach (var url in _selectedPhoneAppItem.AppUrls)
{
AddWebsiteInputControl(url, true); // 填充并设置为只读
}
// 如果没有网站,也添加一个只读的空输入框
if (_selectedPhoneAppItem.AppUrls.Count == 0)
{
AddWebsiteInputControl("", true);
}
SetInputAreaReadOnly(true); // 默认只读
SaveProjectButton.Content = "更新项目"; // 改变按钮文本
}
else
{
// 如果没有选中项,清空并设置为只读
ClearInputArea();
SetInputAreaReadOnly(true);
SaveProjectButton.Content = "保存项目"; // 恢复按钮文本
}
}
// 清空输入区域的辅助方法
private void ClearInputArea()
{
AppNameInputTextBox.Text = string.Empty;
WebsitesStackPanel.Children.Clear(); // 清空所有网站输入框
_websiteCounter = 0; // 重置计数器
AddWebsiteInputControl(); // 重新添加一个默认的网站输入框
}
// 设置输入区域只读状态的辅助方法
private void SetInputAreaReadOnly(bool isReadOnly)
{
AppNameInputTextBox.IsReadOnly = isReadOnly;
// 网站添加按钮
// 修复点:将 FindName 返回的 object 转换为 Button 类型
Button addWebsiteButton = (WebsitesStackPanel.Parent as ScrollViewer)?.FindName("AddWebsiteButton") as Button;
if (addWebsiteButton != null)
{
addWebsiteButton.IsEnabled = !isReadOnly;
}
// 迭代所有动态添加的网站输入框和删除按钮
foreach (UIElement child in WebsitesStackPanel.Children)
{
if (child is StackPanel websiteEntryPanel)
{
if (websiteEntryPanel.Children.FirstOrDefault() is TextBox websiteTextBox)
{
websiteTextBox.IsReadOnly = isReadOnly;
}
if (websiteEntryPanel.Children.LastOrDefault() is Button deleteButton)
{
deleteButton.IsEnabled = !isReadOnly;
}
}
}
SaveProjectButton.IsEnabled = !isReadOnly || _selectedPhoneAppItem != null; // 保存按钮在编辑模式下可用,或者在有选中项时可用(虽然在只读模式下通常不可用)
// 这里的逻辑是:如果不是只读模式,保存按钮可用。如果是只读模式,但有选中项,
// 那么只有“编辑项目”被点击后才会解除只读。
// 调整为:只有在非只读模式下才允许保存
SaveProjectButton.IsEnabled = !isReadOnly;
EditProjectButton.IsEnabled = isReadOnly && _selectedPhoneAppItem != null; // 只有在只读模式且有选中项时,编辑按钮才可用
}
// 辅助方法:显示消息对话框
private async void ShowMessageDialog(string title, string content)
{
ContentDialog dialog = new ContentDialog
{
Title = title,
Content = content,
CloseButtonText = "确定",
XamlRoot = this.Content.XamlRoot
};
await dialog.ShowAsync();
}
}

View File

@ -48,6 +48,11 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\WinUINotes.Grpc\WinUINotes.Grpc.csproj" /> <ProjectReference Include="..\WinUINotes.Grpc\WinUINotes.Grpc.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Page Update="PhoneAppBinderPage.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup> <ItemGroup>
<Page Update="FileUploadPage.xaml"> <Page Update="FileUploadPage.xaml">
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>