抚顺市网站建设_网站建设公司_改版升级_seo优化
2026/1/2 8:04:40 网站建设 项目流程

自己写一个ObjectDataProvider类

ObjectDataProvider.cs代码

using CommunityToolkit.Mvvm.ComponentModel;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Xml.Linq;
using System.Xml.XPath;
using Avalonia.Platform;
using System.Diagnostics;
using System.Linq;namespace Shares.Avalonia
{public partial class ObjectDataProvider : ObservableObject{[ObservableProperty]private Type? objectType;[ObservableProperty]private string? methodName;[ObservableProperty]private string? source;[ObservableProperty]private string? xPath;[ObservableProperty]private object? data;private bool isRefreshing;public ObjectDataProvider(){PropertyChanged += (_, e) =>{if (e.PropertyName is nameof(ObjectType)or nameof(MethodName)or nameof(Source)or nameof(XPath)){Refresh();}};}public void Refresh(){if (isRefreshing)return;isRefreshing = true;try{if (ObjectType != null && !string.IsNullOrWhiteSpace(MethodName)){Data = CallObjectMethod();return;}if (!string.IsNullOrWhiteSpace(Source) && !string.IsNullOrWhiteSpace(XPath)){Data = LoadFromXml();return;}Data = null;}finally{isRefreshing = false;}}private object? CallObjectMethod(){try{var instance = CreateInstanceEvenWithoutDefaultCtor(ObjectType!);var method = ObjectType!.GetMethod(MethodName!);return method?.Invoke(instance, null);}catch (Exception ex){Debug.WriteLine($"[ObjectDataProvider] Method invoke error: {ex}");return null;}}private object? LoadFromXml(){try{var uri = new Uri(Source!, UriKind.RelativeOrAbsolute);using var stream = AssetLoader.Open(uri);var doc = XDocument.Load(stream);var nodes = doc.XPathSelectElements(XPath!);// 只在 ObjectType 为空时推断,且避免循环触发if (ObjectType == null){var nodeName = GetLastNodeNameFromXPath(XPath!);var inferred = FindTypeByName(nodeName);if (inferred != null && inferred != ObjectType)ObjectType = inferred;// 若仍然找不到类型 → 返回 XElement 列表if (ObjectType == null)return new List<XElement>(nodes);}var listType = typeof(List<>).MakeGenericType(ObjectType!);IList list = (IList)Activator.CreateInstance(listType)!;foreach (var node in nodes){var obj = CreateObjectFromXml(node);if (obj != null)list.Add(obj);}return list;}catch (Exception ex){Debug.WriteLine($"[ObjectDataProvider] XML load error: {ex}");return null;}}private object? CreateObjectFromXml(XElement node){try{var instance = CreateInstanceEvenWithoutDefaultCtor(ObjectType!);if (instance == null)return null;foreach (var prop in ObjectType!.GetProperties(BindingFlags.Public | BindingFlags.Instance)){// 先查找 Elementvar el = node.Element(prop.Name);string? xmlValue = el?.Value;// 查找 Attributeif (xmlValue == null){var attr = node.Attribute(prop.Name);xmlValue = attr?.Value;}if (xmlValue == null)continue;try{object? converted = ConvertXmlValue(xmlValue, prop.PropertyType);if (converted != null || prop.PropertyType.IsClass)prop.SetValue(instance, converted);}catch (Exception ex){Debug.WriteLine($"[ObjectDataProvider] Convert error on {prop.Name}: {ex}");}}return instance;}catch (Exception ex){Debug.WriteLine($"[ObjectDataProvider] Object create error: {ex}");return null;}}// 支持 Enum、Nullable<T>、基本类型private static object? ConvertXmlValue(string value, Type targetType){try{// Nullable<T>var underlying = Nullable.GetUnderlyingType(targetType);if (underlying != null)return Convert.ChangeType(value, underlying, CultureInfo.InvariantCulture);// Enumif (targetType.IsEnum)return Enum.Parse(targetType, value, ignoreCase: true);// 默认行为return Convert.ChangeType(value, targetType, CultureInfo.InvariantCulture);}catch{return null;}}private static object? CreateInstanceEvenWithoutDefaultCtor(Type type){try{var defaultCtor = type.GetConstructor(Type.EmptyTypes);if (defaultCtor != null)return defaultCtor.Invoke(null);// 使用“参数最少构造器”var ctor = type.GetConstructors().OrderBy(c => c.GetParameters().Length).First();var parameters = ctor.GetParameters();var args = new object?[parameters.Length];for (int i = 0; i < parameters.Length; i++)args[i] = GetDefaultValue(parameters[i].ParameterType);return ctor.Invoke(args);}catch (Exception ex){Debug.WriteLine($"[ObjectDataProvider] Create instance error: {ex}");return null;}}private static object? GetDefaultValue(Type t){if (t.IsValueType)return Activator.CreateInstance(t);return null;}private static string GetLastNodeNameFromXPath(string xpath){var p = xpath.Trim().Split('/', StringSplitOptions.RemoveEmptyEntries);return p.Length > 0 ? p[^1] : "";}private static Type? FindTypeByName(string name){try{foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()){foreach (var t in asm.GetTypes()){if (t.Name.Equals(name, StringComparison.OrdinalIgnoreCase))return t;}}return null;}catch (Exception ex){Debug.WriteLine($"[ObjectDataProvider] Find type error: {ex}");return null;}}}
}

BindToObjectDataProvider.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"Height="550" Width="400"x:Class="AvaloniaUI.BindToObjectDataProvider"xmlns:data="using:AvaloniaUI.Demos.Book._19.StoreDatabase"Title="BindToObjectDataProvider"><Window.Resources><!--<ObjectDataProvider x:Key="products"ObjectType="data:StoreDb1"MethodName="GetProducts"/>--><ObjectDataProvider x:Key="products"Source="avares://AvaloniaUI/Resources/Datas/store.xml"XPath="/NewDataSet/Products"ObjectType="data:Product"/>
</Window.Resources><Grid RowDefinitions="*,auto,*"><Grid RowDefinitions="auto,*"><TextBlock Margin="5">ObjectDataProvider Example...</TextBlock><ListBox Grid.Row="1"x:Name="lstProducts"Margin="5"ItemsSource="{Binding Source={StaticResource products}, Path=Data}"><ListBox.ItemTemplate><DataTemplate x:DataType="data:Product"><TextBlock Text="{Binding ModelName}" /></DataTemplate></ListBox.ItemTemplate></ListBox></Grid><GridSplitter Grid.Row="1"Height="5"HorizontalAlignment="Stretch"VerticalAlignment="Bottom"ResizeDirection="Rows"ResizeBehavior="PreviousAndNext" /><Border Grid.Row="2"Padding="7"Margin="7"Background="LightSteelBlue"><Grid DataContext="{Binding #lstProducts.SelectedItem}" x:DataType="data:Product"RowDefinitions="auto,auto,auto,auto,*"ColumnDefinitions="auto,*"><TextBlock Margin="7">Model Number:</TextBlock><TextBox Margin="5"Grid.Column="1"Text="{Binding ModelNumber}" /><TextBlock Margin="7"Grid.Row="1">Model Name:</TextBlock><TextBox Margin="5"Grid.Row="1"Grid.Column="1"Text="{Binding ModelName}" /><TextBlock Margin="7"Grid.Row="2">Unit Cost:</TextBlock><TextBox Margin="5"Grid.Row="2"Grid.Column="1"Text="{Binding UnitCost}" /><TextBlock Margin="7,7,7,0"Grid.Row="3">Description:</TextBlock><ScrollViewer Grid.Row="4"Grid.Column="0"Grid.ColumnSpan="2"><TextBox Margin="7"AcceptsReturn="True"TextWrapping="Wrap"Text="{Binding Description}" /></ScrollViewer></Grid></Border></Grid>
</Window>

BindToObjectDataProvider.axaml.cs代码

using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;namespace AvaloniaUI;public partial class BindToObjectDataProvider : Window
{public BindToObjectDataProvider(){InitializeComponent();}
}

运行效果

image

 

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询