目录
1.基类设计
基类定义-BaseModel 实现数据更新通知接口
public class BaseModel : System.ComponentModel.INotifyPropertyChanged
{
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
}
ViewModel基类实现-BaseViewModel
UIElement对象使用类型VisualElement,它是ContentPage/ContentView 等的基类,但Window不是,因为MAUI框架的原因,Window的定义跟桌面端的Window不一样,MAUI的Window作为唯一主界面使用,同时Window对象无法作为对话框的形式弹出,所以Window就可以单独处理。
一般的设计逻辑是 实例化Page,然后再绑定ViewModel实例
this.BindingContext = new ViewModels.VM_MainWindow(this);
基类的设计是先初始化ViewModel实例,传入Page的类型,在初始化时同时初始化UI,再互相绑定。
下面是实现的代码:
public class BaseViewModel : BaseModel
{
//程序的主命名空间
public string UINameSapce = "";
//类名
public string UIElementName = "";
public VisualElement UIElement { get; set; }
private System.Type UIType;
/// <summary>
/// ViewModel基类 需要传UI界面的全名(FullName)参数
/// </summary>
/// <param name="uiType">UI界面的类型</param>
public BaseViewModel(System.Type uiType)
{
try
{
UIType = uiType;
UINameSapce = uiType.Namespace;
SetUIElement();
UIElement.BindingContext = this;
}
catch (System.Exception ex)
{
throw ex;
}
}
/// <summary>
/// ViewModel基类,直接传入UI界面对象
/// </summary>
/// <param name="ui"></param>
public BaseViewModel(VisualElement ui)
{
try
{
UIType = ui.GetType();
UINameSapce = UIType.Namespace;
UIElementName = UIType.FullName;
UIElement = ui;
UIElement.Loaded += Page_Loaded;
UIElement.Unloaded += Page_Unloaded;
//UIElement.BindingContext = this;
}
catch (System.Exception ex)
{
throw ex;
}
}
#region 通过反射创建对应的UI元素
/// <summary>
/// 页面加载时触发
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected virtual void Page_Loaded(object sender, EventArgs e)
{
LoadData();
}
/// <summary>
/// 页面退出时触发
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected virtual void Page_Unloaded(object sender, EventArgs e)
{
UnLoadData();
}
/// <summary>
/// 页面加载时初始化数据
/// 会在PageLoad页面触发
/// 重写后,静态页面按需调用
/// </summary>
public virtual void LoadData()
{
}
/// <summary>
/// 页面销毁时处理数据
/// 会在PageUnLoad页面触发
/// 重写后,静态页面按需调用
/// </summary>
public virtual void UnLoadData()
{
}
/// <summary>
/// 根据VM名称,反射对应类型的UI实例
/// </summary>
internal void SetUIElement()
{
System.Type childType = this.GetType();//获取子类的类型
UIElementName = this.GetType().FullName;
UIElement = (VisualElement)GetElement();
UIElement.Loaded += Page_Loaded;
UIElement.Unloaded += Page_Unloaded;
}
/// <summary>
/// 用UI全名称(FullName)进行反射UI实例
/// </summary>
/// <typeparam name="E"></typeparam>
/// <param name="UIElementFullName"></param>
/// <returns></returns>
public object GetElement()
{
if (UIType != null)
{
return System.Activator.CreateInstance(UIType);
}
else
{
throw new System.Exception("UIType为空");
}
}
#endregion
#region 异步线程
/// <summary>
/// 异步方法执行事件
/// </summary>
public void AsyncLoad(System.Action action)
{
System.IAsyncResult result = action.BeginInvoke((iar) =>
{
}, null);
}
/// <summary>
/// 异步方法执行事件 带回调方法
/// </summary>
public void AsyncLoad(System.Action action, System.Action callback)
{
System.IAsyncResult result = action.BeginInvoke((iar) =>
{
this.DoMenthodByDispatcher(callback);
}, null);
}
/// <summary>
/// 异步方法执行事件 带参数及带回调方法
/// </summary>
public void AsyncLoad<T>(System.Action<T> action, T para, System.Action callback)
{
System.IAsyncResult result = action.BeginInvoke(para, (iar) =>
{
this.DoMenthodByDispatcher(callback);
}, null);
}
/// <summary>
/// 异步方法执行事件 带参数及带回调方法
/// </summary>
public void AsyncLoad<T, R>(System.Func<T, R> action, T para, System.Action<R> callback)
{
System.IAsyncResult result = action.BeginInvoke(para, (iar) =>
{
var res = action.EndInvoke(iar);
this.DoMenthodByDispatcher<R>(callback, res);
}, null);
}
/// <summary>
/// 异步方法执行事件 带回调方法
/// </summary>
/// <typeparam name="R"></typeparam>
/// <param name="action"></param>
/// <param name="callback"></param>
public void AsyncLoad<R>(System.Func<R> action, System.Action<R> callback)
{
System.IAsyncResult result = action.BeginInvoke((iar) =>
{
var res = action.EndInvoke(iar);
this.DoMenthodByDispatcher<R>(callback, res);
}, null);
}
/// <summary>
/// 使用UI线程执行Action 带参数 默认 异步(BeginInvoke)执行
/// </summary>
/// <typeparam name="T">泛型参数</typeparam>
/// <param name="action">执行的方法</param>
/// <param name="obj">参数</param>
/// <param name="isAsync">是否异步 true-异步 false-同步</param>
public void DoMenthodByDispatcher<T>(System.Action<T> action, T obj, bool isAsync = true)
{
if (isAsync)
{
UIElement?.Dispatcher.DispatchAsync(new System.Action(() =>
{
action(obj);
}));
}
else
{
UIElement?.Dispatcher.Dispatch(new System.Action(() =>
{
action(obj);
}));
}
}
/// <summary>
///使用UI线程执行Action 默认 异步(BeginInvoke)执行
/// </summary>
/// <param name="action"></param>
/// <param name="isAsync">是否异步 true-异步 false-同步</param>
public void DoMenthodByDispatcher(System.Action action, bool isAsync = true)
{
if (isAsync)
{
UIElement?.Dispatcher.DispatchAsync(new System.Action(() =>
{
action();
}));
}
else
{
UIElement?.Dispatcher.Dispatch(new System.Action(() =>
{
action();
}));
}
}
#endregion
}
定义ViewModel的类:
Page类(UI):PersonalPage
对应的VM:VM_PersonalPage
public class VM_PersonalPage:BaseViewModel
{
public VM_PersonalPage() : base(typeof(PersonalPage)) { }
}
2.页面框架
MAUI,我使用的是以Window作为主界面,然后各个页面使用ContentView 进行切换
缺点就是得自己做导航缓存
MAUI不能使用Frame作为导航切换的框架了,更改下Border
<ScrollView Grid.Row="0">
<Border
x:Name="MainFrame"
Content="{Binding PageUri}"
HorizontalOptions="Fill"
VerticalOptions="Fill" />
</ScrollView>
对应的VM实现:
页面切换,切换前做个判断,如果是同一个界面,则不再处理
传入的是Type对象,则进行创建实例,再切换
传入的是Object对象,则直接使用对象进行切换
切换的使用示例:
PageJump(typeof(VM_HomePage));
以下是页面切换部分的实现代码:
#region 页面跳转
private ContentView _pageUri;
/// <summary>
/// 加载的页面属性
/// </summary>
public ContentView PageUri
{
get { return _pageUri; }
set
{
_pageUri = value;
OnPropertyChanged();
}
}
/// <summary>
/// 页面跳转锁对象
/// </summary>
private bool _lock_pagejump = false;
/// <summary>
/// 在跳转之前检查状态是否可以进行跳转界面
/// </summary>
/// <param name="obj"></param>
private bool BeforeJumpCheck(object obj)
{
bool isPass = false;
if (!_lock_pagejump)
{
try
{
_lock_pagejump = true;
//如果同一页面则不刷新
if (obj is BaseViewModel && PageUri?.GetType().FullName == (((BaseViewModel)obj).UIElement as ContentView)?.GetType().FullName)
{
return false;
}
isPass = true;
}
catch (Exception ex)
{
LogOperate.Error("BeforeJumpCheck 异常", ex);
}
finally
{
_lock_pagejump = false;
}
}
return isPass;
}
/// <summary>
/// 页面跳转
/// </summary>
/// <param name="vmtype">ViewModel 的类型 typeof()</param>
/// <param name="args">ViewModel 的构造函数入参</param>
internal void PageJump(Type vmtype, object[] args = null)
{
MainWin?.Dispatcher.Dispatch(() =>
{
object obj = null;
//根据类型进行反射生成实例
if (args != null && args.Length > 0)
{
obj = vmtype.Assembly.CreateInstance(vmtype.FullName, false, System.Reflection.BindingFlags.CreateInstance, null, args, null, null);
}
else
{
obj = vmtype.Assembly.CreateInstance(vmtype.FullName);
}
if (BeforeJumpCheck(obj))
{
PageUri = (obj as BaseViewModel).UIElement as ContentView;
}
else
{
obj = null;
}
});
}
/// <summary>
/// 页面跳转,加载缓存中的vm数据
/// </summary>
/// <param name="vmobject">vm对象</param>
internal void PageJump(object vmobject)
{
MainWin?.Dispatcher.Dispatch(() =>
{
if (vmobject is BaseViewModel)
{
if (BeforeJumpCheck(vmobject))
{
PageUri = (vmobject as BaseViewModel).UIElement as ContentView;
}
else
{
vmobject = null;
}
}
});
}
#endregion


1202

被折叠的 条评论
为什么被折叠?



