mc:Ignorable="d" WindowStartupLocation="CenterScreen" Title="MainWindow" Style="{StaticResource BaseWindowStyle}"> <Window.Resources>
<ObjectDataProvider MethodName="GetValues" ObjectType="{x:Type sys:Enum}" x:Key="MyLightMode">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="api:LightMode"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider> <ObjectDataProvider MethodName="GetValues" ObjectType="{x:Type sys:Enum}" x:Key="MySortingLogStyle">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="e:ESortingLogStyle"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider> <valueConverter:ChannelValueConverter x:Key="ChannelValueConverter"/>
<valueConverter:SortingLogStyleValueConverter x:Key="SortingLogStyleValueConverter"/>
</Window.Resources> <i:Interaction.Triggers>
<prism:InteractionRequestTrigger SourceObject="{Binding ShowMessageBoxRequest}">
<utils:CustomPopupWindowAction CenterOverAssociatedObject="True" IsModal="True">
<prism:PopupWindowAction.WindowContent>
<dlg:ShowMessageUserControl/>
</prism:PopupWindowAction.WindowContent>
</utils:CustomPopupWindowAction>
</prism:InteractionRequestTrigger> <prism:InteractionRequestTrigger SourceObject="{Binding ProcessSortingUIRequest}">
<ta:ProcessSortingUITriggerAction/>
</prism:InteractionRequestTrigger>
</i:Interaction.Triggers> <Grid>
<Viewbox Stretch="Fill" >
<Canvas Height="648" Width="1024">
<Label Content="{Binding CurrentErrorInfo}" Canvas.Top="597" Background="Red" Foreground="White" Width="1013" Height="36">
<Label.Style>
<Style TargetType="{x:Type Label}" BasedOn="{StaticResource ContentAlignmentLabelStyle}">
<Setter Property="Padding" Value="3,3"/>
<Style.Triggers>
<Trigger Property="Content" Value="{x:Null}">
<Setter Property="Visibility" Value="Collapsed"/>
</Trigger>
<Trigger Property="Content" Value="">
<Setter Property="Visibility" Value="Collapsed"/>
</Trigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
</Canvas>
</TabItem>
</TabControl>
<StackPanel Visibility="{Binding AutoTagSelfCheckingProgressVisibility,UpdateSourceTrigger=PropertyChanged}" Orientation="Horizontal" Background="White" Canvas.Left="1" Canvas.Top="515" Width="1023" Height="82">
<Label Content=" 自检中..." Style="{StaticResource ContentAlignmentLabelStyle}" />
<ProgressBar Height="42" Value="{Binding AutoTagSelfCheckingProgressValue, UpdateSourceTrigger=PropertyChanged}" Width="882" Minimum="0" Maximum="100" Margin="0,20" Foreground="Blue"/>
</StackPanel>
</Canvas>
</Viewbox>
</Grid>
</base:BaseWindow>...:INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
// 是不是invoke已经可以保证线程安全了?
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
} string currentErrorInfo;
public string CurrentErrorInfo
{
get
{ return currentErrorInfo; }
set
{
if (currentErrorInfo != value)
{
Interlocked.Exchange(ref currentErrorInfo, value);
OnPropertyChanged(nameof(CurrentErrorInfo));
}
}
} object autoTagSelfCheckingProgressVisibility = Visibility.Collapsed;
public Visibility AutoTagSelfCheckingProgressVisibility
{
get
{ return (Visibility)autoTagSelfCheckingProgressVisibility; }
set
{
if ((Visibility)autoTagSelfCheckingProgressVisibility != value)
{
Interlocked.Exchange(ref autoTagSelfCheckingProgressVisibility, value);
OnPropertyChanged(nameof(AutoTagSelfCheckingProgressVisibility));
}
}
}
比如
一个是绑定改变label文字的 CurrentErrorInfo
一个是改变进度条控件显示的AutoTagSelfCheckingProgressVisibility
目前都是直接在ViewModel里某个线程里直接修改绑定值了,倒是一直也没出问题, ThreadPool.QueueUserWorkItem(obj =>
{
CurrentErrorInfo="111"; AutoTagSelfCheckingProgressVisibility = Visibility.Visible;
});
是不是最好还是这样?:
Application.Current.Dispatcher.Invoke((Action)(()=>{
AutoTagSelfCheckingProgressVisibility = Visibility.Visible;
}));
有没有必要?为什么不用也不会出错,报跨线程处理UI的错误 public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
// 是不是invoke已经可以保证线程安全了?
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
另外,绑定Visibility属性时,如何设置默认值Collapsed,否则程序启动控件会显示,直到绑定值Collapsed生效后消失
public MainWindow()
{
InitializeComponent(); this.ContentRendered += MainWindow_ContentRendered;
} private void MainWindow_ContentRendered(object sender, EventArgs e)
{
this.DataContext = new MainViewModel();Visibility="{Binding AutoTagSelfCheckingProgressVisibility,UpdateSourceTrigger=PropertyChanged}"
解决方案 »
- chart设置
- 怎么实现雅虎邮箱地址那样自动添加后缀的输入方式
- c#定时启动和关闭程序
- .net2005,C#,连接SQL数据库问题
- C# C/S程序局域网传输文件,客户端100台左右,请问用什么方案或者技术好
- Math.Round()能取整数么?
- 图形类如果加入鼠标事件?
- 請問高手, C#中用哪一種功能(方法)取代了以前宏的功能(方法)?
- 请问如何取得rowstate为delete的记录中的内容?不会报错误:can't access the deleted row through the row
- 急急急:如何把数据库中Image字段转换为数据流???
- Treeview重绘的问题
- 在引用AxAcroPDFLib的时候报错,FileLoad是否缺少 using 指令或程序集引用?
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
App.Current?.Dispatcher?.Invoke((Action)(() =>
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}));
}
还是在这里加了一个,为了PropertyChanged订阅内部触发保险起见
public Visibility AutoTagSelfCheckingProgressVisibility
-》为什么要用object而不用Visibility 。
UI控件和属性不同,操作的只是一个WPF中的属性而已,WPF中的属性会映射到对应的.net属性,自然不会出错。如果使用跨线程去操作WPF中的一个Button,比如:
Task.Run(() =>
{
// 操作button
});
会报UI错误,因为button不是由工作者线程创建的。
因为 Interlocked.Exchange原子操作的参数必须是可引用对象,否则报错,我会在多线程里读写这个值PropertyChanged内部机制不是很了解,网上看过一篇文章试图去从.net源码查看其何时注册订阅和执行改变,但不幸的是那文章太监了,藏的太深作者没往下走了,我就怕PropertyChanged最终执行还是去调用UI控件,类似txtABC.txt="111"
有线程安全的考虑的话,应该是在cs文件中考虑吧。要不然还考虑什么前后端分离
因为 Interlocked.Exchange原子操作的参数必须是可引用对象,否则报错,我会在多线程里读写这个值PropertyChanged内部机制不是很了解,网上看过一篇文章试图去从.net源码查看其何时注册订阅和执行改变,但不幸的是那文章太监了,藏的太深作者没往下走了,我就怕PropertyChanged最终执行还是去调用UI控件,类似txtABC.txt="111"
一般使用PropertyChanged就不会进行txtABC.txt="111"这种赋值方式,如果这样,那就不要用binding了,也就不存在view与viewmodel的分离了。
不是手动去自己赋值,而且想知道binding后,PropertyChanged的内部机制最后是如何实际更新UI属性的,.net源码里不知道是否能看出来
不是手动去自己赋值,而且想知道binding后,PropertyChanged的内部机制最后是如何实际更新UI属性的,.net源码里不知道是否能看出来
估计看不出来的
不是手动去自己赋值,而且想知道binding后,PropertyChanged的内部机制最后是如何实际更新UI属性的,.net源码里不知道是否能看出来
估计看不出来的那先这样把,加个保险点,性能上也没啥损失
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
而不是
PropertyChanged?(this, new PropertyChangedEventArgs(propertyName));
那只是改变 VM 的属性,你又没有操作 UI 控件,纠结 UI 干什么呢?如果要纠结 Control.Invoke/BeginInvoke,那么你就不要使用你的那个所谓的 MVVM 框架了,说明它设计有问题。它自然是需要处理 control.BeginInvoke/Invoke,跟你完全无关。