Avalonia学习
1、图片
- 图片显示
Source设置为固定的图片全路径时,可以直接设置;
但是用Binding绑定图片时,需要是Bitmap类型,即 Avalonia.Media.Imaging.Bitmap(Stream stream);
<Image Grid.Column="0" Grid.Row="2" Width="11" Source="/Assets/icon/fav.png" HorizontalAlignment="Center" VerticalAlignment="Center"></Image> <Image Cursor="Hand" Name="Signature" Tapped="Tapped_Detail" Source="{Binding MailDetailModel.SignImage, Converter={StaticResource ImgConverter}}"></Image>
- 图片单击
1、使用Tapped=“Tapped_Detail” Tapped_Detail定义在页面后端的cs代码中
2、使用Image.GestureRecognizers,其中没有TapGestureRecognizer【不可用】
3、使用<Button>包裹,命令可写在viewmodel中
注意设置Button的属性
<Button Command="{Binding ShowDecryptCert}" BorderThickness="0" Background="White"> <Image Source="{Binding MailDetailModel.ResolveResult, Converter={StaticResource MailResolveResultDecryptConverter}}"></Image> </Button>
2、文本TextBlock
- 文本截断与显示不全用ToolTip
<TextBlock Text="{Binding Subject}" Width="180" TextTrimming="CharacterEllipsis" TextWrapping="NoWrap" ToolTip.Tip="{Binding Subject}"></TextBlock>
参考:WPF 文字换行TextWrapping 显示不全用省略号TextTrimming 显示不全弹提示内容ToolTip
注意宽度的设置:
如果控件位于grid中,则设置列宽,如下:
<Grid VerticalAlignment="Center" Background="Transparent"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"></ColumnDefinition> <ColumnDefinition Width="180"></ColumnDefinition> <ColumnDefinition Width="Auto"></ColumnDefinition> </Grid.ColumnDefinitions> <TextBlock x:Name="content" Margin="10" Text="{Binding FolderName}" FontSize="14" Grid.Column="1" TextTrimming="CharacterEllipsis" TextWrapping="NoWrap" ToolTip.Tip="{Binding FolderName}"/>
ToolTip.Placement="Right" 右下角
Left:左下角
AnchorAndGravity:底部中间
想置于上方,必须同时设置这两个:ToolTip.Placement="Top" ToolTip.VerticalOffset="-5" 【因为原点在左上角,往下为正】
- 文本绑定多个值,单击事件获取
通过ToolTip去传递另一个对象(不需要其显示,通过ShowDelay 来控制其不显示【鼠标放在上面的显示需要等待的毫秒数】)
<TextBlock Cursor="Hand" Name="Receiver" Tapped="ShowSenderInfo" Classes="B" Foreground="{StaticResource GrayBrush3}" Text="{Binding NickName}" ToolTip.Tip="{Binding Address}" ToolTip.ShowDelay="3000"></TextBlock>
后台获取ToolTip绑定的对象
public async void ShowSenderInfo(object Sender, Avalonia.Interactivity.RoutedEventArgs e) { try { var sender = Sender as TextBlock; if (sender == null) return; string mailaddress = ToolTip.GetTip(sender).ToString(); //联系人的邮箱地址 } catch (Exception) { } }
3、ListBox
右键事件
PointerPressed 事件,xml中 PointerPressed="ListBox_MouseTap"
private void ListBox_MouseTap(object sender, Avalonia.Input.PointerPressedEventArgs e) { try { if (e.MouseButton == Avalonia.Input.MouseButton.Right) { MyListBox control = null; if (sender is MyListBox) control = sender as MyListBox; if (control != null && control.SelectedItem != null) { MailListModel model = control.SelectedItem as MailListModel; if (model != null) { model.IsRightSelected = true; vm.SelectedItem = model; } } } } catch (Exception ex) { LogHelper.AddErrorLog(ex); } }
参考:.NET 跨平台框架Avalonia UI: 填坑指北(一):熟悉UI操作
4、更新UI
后台线程 想执行UI操作,必须用以下方式
await Avalonia.Threading.Dispatcher.UIThread.InvokeAsync(() => { MailCache.Instance.ShowMailFolders(mailFolderInfos); });
5、WebView
1、同一个页面没法用两个
2、给webview设置值后,执行后续逻辑 用Task.Delay().ContinueWith() 以防止webview的卡顿与延迟。
//防止切换卡顿 await Task.Delay(100).ContinueWith(async t => { .... });
6、Window窗体
不显示 顶部:SystemDecorations="BorderOnly"
7、样式Style
- 样式引用
<!--Classes="MenuList"的ListBox的样式-->
<Style Selector="ListBox.MenuList">
</Style>
<ListBox x:Name="lvMenu" Classes="MenuList" Items="{Binding MenuNames}" ></ListBox>
- 字体
避免中文乱码:<Setter Property="FontFamily" Value="苹方-简,Microsoft YaHei,宋体-简"></Setter>
下划线正常显示:<Setter Property="FontFamily" Value="Microsoft YaHei"></Setter>
8、Grid
<RowDefinition Height="Auto"></RowDefinition>与<RowDefinition Height="*"></RowDefinition> 的区别
前者的高度会根据其元素的高度而定,当窗体最大化后也不会变;
后者的高度在窗体最大化时会改变。
学习
论坛:https://gitter.im/AvaloniaUI/Avalonia
常见问题
1、在Linux环境下,打开文件对话框报错:String reference not set to an instance of a String. (Parameter 's')
具体报错信息:String reference not set to an instance of a String. (Parameter 's')
at System.Text.Encoding.GetBytes(String s)
at Avalonia.X11.X11Window.SetTitle(String title)
at Avalonia.Controls.Window.<>c.<.cctor>b__25_0(Window s, AvaloniaPropertyChangedEventArgs e)
at System.Reactive.Subjects.Subject`1.OnNext(T value) in /_/Rx.NET/Source/src/System.Reactive/Subjects/Subject.cs:line 148
at Avalonia.AvaloniaObject.RaisePropertyChanged[T](AvaloniaPropertyChangedEventArgs`1 change)
at Avalonia.AvaloniaObject.Avalonia.PropertyStore.IValueSink.ValueChanged[T](AvaloniaPropertyChangedEventArgs`1 change)
at Avalonia.ValueStore.SetValue[T](StyledPropertyBase`1 property, T value, BindingPriority priority)
at Avalonia.Controls.Window.set_Title(String value)
at Avalonia.Dialogs.ManagedFileDialogExtensions.ManagedSystemDialogImpl`1.Show(SystemDialog d, Window parent, ManagedFileDialogOptions options)
at Avalonia.Dialogs.ManagedFileDialogExtensions.ManagedSystemDialogImpl`1.ShowFileDialogAsync(FileDialog dialog, Window parent)
at Avalonia.Controls.SaveFileDialog.ShowAsync(Window parent)
at mesignpctest.Helper.FileDialogHelper.OpenSaveFileDialog(Window win, String fileName) in F:\WoTProject\MeSignClient\MeSign\mesignpctest\Helper\FileDialogHelper.cs:line 180
at mesignpctest.Helper.AttachmentFileHelper.SaveFile(Window win, AttachmentListModel model, Boolean fromAttachList)
in F:\WoTProject\MeSignClient\MeSign\mesignpctest\Helper\AttachmentFileHelper.cs:line 154
注意 ,红色部分
找到代码,
//弹出文件目录选择框 var fileDialog = new SaveFileDialog(); fileDialog.InitialFileName = fileName; //获取选中的路径地址 var path = await fileDialog.ShowAsync(win); return path;
可以发现 对话框没有设置Title,改为如下 即可
var fileDialog = new SaveFileDialog() { Title = AppResource.另存为 };
2、Main throw a exception:System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index')
at System.Collections.Generic.List`1.get_Item(Int32 index)
at System.Collections.ObjectModel.Collection`1.System.Collections.IList.get_Item(Int32 index)
at Avalonia.Controls.Utils.IEnumerableUtils.ElementAt(IEnumerable items, Int32 index)
at Avalonia.Controls.Presenters.ItemVirtualizerSimple.RecycleContainers()
at Avalonia.Controls.Presenters.ItemVirtualizerSimple.RecycleContainersOnRemove()
at Avalonia.Controls.Presenters.ItemVirtualizerSimple.ItemsChanged(IEnumerable items, NotifyCollectionChangedEventArgs e)
at Avalonia.Controls.Presenters.ItemsPresenter.ItemsChanged(NotifyCollectionChangedEventArgs e)
at Avalonia.Controls.Presenters.ItemsPresenterBase.set_Items(IEnumerable value)
at Avalonia.Controls.Presenters.ItemsPresenterBase.<>c.<.cctor>b__7_2(ItemsPresenterBase o, IEnumerable v)
at Avalonia.DirectProperty`2.InvokeSetter(IAvaloniaObject instance, BindingValue`1 value)
at Avalonia.AvaloniaObject.SetDirectValueUnchecked[T](DirectPropertyBase`1 property, BindingValue`1 value)
at Avalonia.AvaloniaObject.DirectBindingSubscription`1.OnNext(BindingValue`1 value)
at Avalonia.Reactive.SingleSubscriberObservableBase`1.PublishNext(T value)
at Avalonia.Reactive.TypedBindingAdapter`1.OnNext(BindingValue`1 value)
at Avalonia.Reactive.SingleSubscriberObservableBase`1.PublishNext(T value)
at Avalonia.Reactive.BindingValueAdapter`1.OnNext(T value)
at Avalonia.Reactive.SingleSubscriberObservableBase`1.PublishNext(T value)
at Avalonia.Data.TemplateBinding.PublishValue()
at Avalonia.AvaloniaObject.RaisePropertyChanged[T](AvaloniaPropertyChangedEventArgs`1 change)
at Avalonia.AvaloniaObject.RaisePropertyChanged[T](AvaloniaProperty`1 property, Optional`1 oldValue, BindingValue`1 newValue, BindingPriority priority)
at Avalonia.AvaloniaObject.SetAndRaise[T](AvaloniaProperty`1 property, T& field, T value)
at Avalonia.Controls.ItemsControl.set_Items(IEnumerable value)
at Avalonia.Controls.ItemsControl.<>c.<.cctor>b__8_4(ItemsControl o, IEnumerable v)
at Avalonia.DirectProperty`2.InvokeSetter(IAvaloniaObject instance, BindingValue`1 value)
at Avalonia.AvaloniaObject.SetDirectValueUnchecked[T](DirectPropertyBase`1 property, BindingValue`1 value)
at Avalonia.AvaloniaObject.DirectBindingSubscription`1.<>c__DisplayClass7_0.<OnNext>b__0()
at Avalonia.Threading.JobRunner.RunJobs(Nullable`1 priority)
at Avalonia.Win32.Win32Platform.WndProc(IntPtr hWnd, UInt32 msg, IntPtr wParam, IntPtr lParam)
at Avalonia.Win32.Interop.UnmanagedMethods.DispatchMessage(MSG& lpmsg)
at Avalonia.Win32.Win32Platform.RunLoop(CancellationToken cancellationToken)
at Avalonia.Threading.Dispatcher.MainLoop(CancellationToken cancellationToken)
at Avalonia.Controls.ApplicationLifetimes.ClassicDesktopStyleApplicationLifetime.Start(String[] args)
at Avalonia.ClassicDesktopStyleApplicationLifetimeExtensions.StartWithClassicDesktopLifetime[T](T builder, String[] args, ShutdownMode shutdownMode)
at mesign.pc.Program.Main(String[] args) in F:\WoTProject\MeSignClient\MeSign\mesign.pc\Program.cs:line 22
场景:一直快速切换文件夹时 出现闪退
解决方法:查看Avalonia.Controls.Presenters.ItemVirtualizerSimple 源代码,,
RecycleContainersOnRemove() 中RecycleContainers()
联想到 切换文件夹时的代码,每次切换时 对MailItems做了一次清空,然后给MailItems赋值。。
改为:切换文件夹时不清空列表,直接对它进行赋值。 文件夹没有邮件时才清空列表。