最近在研究用C#开发安卓应用,头大呀,这方面的资料真的非常少,毕竟非主流呀。
一开始用了MAUI,谁知道用VS2022创建的初始项目都跑不起来,各种BUG。
无奈呀,最后只能找上它了,没错,就是Xamarin.Forms;
一上手发现,开发模式如此的熟悉,毕竟之前一直玩WPF;
所以就自个琢磨着把WPF那一套VM的基类实现转移了过来,发现一样好用呀;
不多说直接上代码:
首先是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));
}
}
}
接下来就是BaseViewModel啦
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;
OnLoad();
}
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.BindingContext = this;
}
catch (System.Exception ex)
{
throw ex;
}
}
#region 界面加载方法
/// <summary>
/// 需要手动调用
/// </summary>
public virtual void OnLoad()
{
}
/// <summary>
/// 需要手动调用
/// </summary>
public virtual void UnLoad()
{
}
#endregion
#region 通过反射创建对应的UI元素
/// <summary>
/// 根据VM名称,反射对应类型的UI实例
/// </summary>
internal void SetUIElement()
{
System.Type childType = this.GetType();//获取子类的类型
UIElementName = this.GetType().FullName;
UIElement = (View)GetElement();
}
/// <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>
public void DoMenthodByDispatcher<T>(System.Action<T> action, T obj)
{
UIElement?.Dispatcher.BeginInvokeOnMainThread(new System.Action(() =>
{
action(obj);
}));
}
/// <summary>
///使用UI线程执行Action 默认 异步(BeginInvoke)执行
/// </summary>
/// <param name="action"></param>
public void DoMenthodByDispatcher(System.Action action)
{
UIElement?.Dispatcher.BeginInvokeOnMainThread(new System.Action(() =>
{
action();
}));
}
#endregion
}
因Xamarin.Forms中没有 Load和UnLoad的事件绑定,所以我在基类添加了两个方法 Load和UnLoad;
Load方法在BaseViewModel构造函数中调用了;
然后UnLoad的话,界面用的Frame控件切换界面,通过属性绑定,在切换时调用UnLoad的方法;
<Frame
x:Name="MainFrame"
Grid.Row="1"
Margin="0"
BackgroundColor="Transparent"
Content="{Binding ViewUri}"
CornerRadius="0"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand" />
private View _viewUri;
/// <summary>
/// 界面Frame对象
/// </summary>
public View ViewUri
{
get { return _viewUri; }
set
{
try
{
if (_viewUri != null)
{
((BaseViewModel)_viewUri.BindingContext).UnLoad();
}
}
catch { }
_viewUri = value;
OnPropertyChanged();
}
}