WPF在不同.Net版本间的兼容性问题
第一次寫博客^_^
之前在做.NET和WPF開發,期間遇到了一些.net不同版本之間兼容性問題,整理了下,留個備份。
.net 3.5的兼容性問題
1. 在.net 3.5中VirtualizingStackPanel.VirtualizationMode沒有Recycling模式(是在.net 4.0后),所以用Standard替代。
??? https://connect.microsoft.com/VisualStudio/feedback/details/346158/virtualizingstackpanel-virtualizationmode-not-working-properly
2. Command & CommandParameter in InputBindings are Properties not Dependency Properties,所以不能在xaml中直接用binding,解決方案自己重新實現Command和CommandParameter的類,里面定義Dependence Properties,再在xaml把相應的Command和CommanParameter定義成StaticResource reference。
New Command class:
using System; using System.Windows; using System.Windows.Input;namespace Sample.WPFUI.Commands {public class CommandReference : Freezable, ICommand{public CommandReference(){}public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(CommandReference),new PropertyMetadata(new PropertyChangedCallback(OnCommandChanged)));public ICommand Command{get { return (ICommand)GetValue(CommandProperty); }set { SetValue(CommandProperty, value); }}#region ICommand Memberspublic bool CanExecute(object parameter){if (Command != null)return Command.CanExecute(parameter);return false;}public void Execute(object parameter){Command.Execute(parameter);}public event EventHandler CanExecuteChanged;private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){CommandReference commandReference = d as CommandReference;ICommand oldCommand = e.OldValue as ICommand;ICommand newCommand = e.NewValue as ICommand;if (oldCommand != null){oldCommand.CanExecuteChanged -= commandReference.CanExecuteChanged;}if (newCommand != null){newCommand.CanExecuteChanged += commandReference.CanExecuteChanged;}}#endregion#region Freezableprotected override Freezable CreateInstanceCore(){throw new NotImplementedException();}#endregion} } View CodeNew CommandParameter class:
using System; using System.ComponentModel; using System.Diagnostics; using System.Reflection; using System.Windows; using System.Windows.Markup;namespace Sample.WPFUI {public class DataResource : Freezable{/// <summary>/// Identifies the <see cref="BindingTarget"/> dependency property./// </summary>/// <value>/// The identifier for the <see cref="BindingTarget"/> dependency property./// </value>public static readonly DependencyProperty BindingTargetProperty = DependencyProperty.Register("BindingTarget", typeof(object), typeof(DataResource), new UIPropertyMetadata(null));/// <summary>/// Initializes a new instance of the <see cref="DataResource"/> class./// </summary>public DataResource(){}/// <summary>/// Gets or sets the binding target./// </summary>/// <value>The binding target.</value>public object BindingTarget{get { return (object)GetValue(BindingTargetProperty); }set { SetValue(BindingTargetProperty, value); }}/// <summary>/// Creates an instance of the specified type using that type's default constructor. /// </summary>/// <returns>/// A reference to the newly created object./// </returns>protected override Freezable CreateInstanceCore(){return (Freezable)Activator.CreateInstance(GetType());}/// <summary>/// Makes the instance a clone (deep copy) of the specified <see cref="Freezable"/>/// using base (non-animated) property values. /// </summary>/// <param name="sourceFreezable">/// The object to clone./// </param>protected sealed override void CloneCore(Freezable sourceFreezable){base.CloneCore(sourceFreezable);}}public class DataResourceBindingExtension : MarkupExtension{private object mTargetObject;private object mTargetProperty;private DataResource mDataResouce;/// <summary>/// Gets or sets the data resource./// </summary>/// <value>The data resource.</value>public DataResource DataResource{get{return mDataResouce;}set{if (mDataResouce != value){if (mDataResouce != null){mDataResouce.Changed -= DataResource_Changed;}mDataResouce = value;if (mDataResouce != null){mDataResouce.Changed += DataResource_Changed;}}}}/// <summary>/// Initializes a new instance of the <see cref="DataResourceBindingExtension"/> class./// </summary>public DataResourceBindingExtension(){}/// <summary>/// When implemented in a derived class, returns an object that is set as the value of the target property for this markup extension./// </summary>/// <param name="serviceProvider">Object that can provide services for the markup extension.</param>/// <returns>/// The object value to set on the property where the extension is applied./// </returns>public override object ProvideValue(IServiceProvider serviceProvider){IProvideValueTarget target = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));mTargetObject = target.TargetObject;mTargetProperty = target.TargetProperty;// mTargetProperty can be null when this is called in the Designer.Debug.Assert(mTargetProperty != null || DesignerProperties.GetIsInDesignMode(new DependencyObject()));if (DataResource.BindingTarget == null && mTargetProperty != null){PropertyInfo propInfo = mTargetProperty as PropertyInfo;if (propInfo != null){try{return Activator.CreateInstance(propInfo.PropertyType);}catch (MissingMethodException){// there isn't a default constructor }}DependencyProperty depProp = mTargetProperty as DependencyProperty;if (depProp != null){DependencyObject depObj = (DependencyObject)mTargetObject;return depObj.GetValue(depProp);}}return DataResource.BindingTarget;}private void DataResource_Changed(object sender, EventArgs e){// Ensure that the bound object is updated when DataResource changes.DataResource dataResource = (DataResource)sender;DependencyProperty depProp = mTargetProperty as DependencyProperty;if (depProp != null){DependencyObject depObj = (DependencyObject)mTargetObject;object value = Convert(dataResource.BindingTarget, depProp.PropertyType);depObj.SetValue(depProp, value);}else{PropertyInfo propInfo = mTargetProperty as PropertyInfo;if (propInfo != null){object value = Convert(dataResource.BindingTarget, propInfo.PropertyType);propInfo.SetValue(mTargetObject, value, new object[0]);}}}private object Convert(object obj, Type toType){try{return System.Convert.ChangeType(obj, toType);}catch (InvalidCastException){return obj;}}} } View Code?Xaml sample:
<cf:CommandReference x:Key="EditTextBoxReturnCommand" Command="{Binding Path=DataContext.ViewModelCommands.EditTextBoxReturnCommand, ElementName=filePaneCloudViewPage}"/> <cf:CommandReference x:Key="EditTextBoxEscapeCommand" Command="{Binding Path=DataContext.ViewModelCommands.EditTextBoxEscapeCommand, ElementName=filePaneCloudViewPage}"/> <TextBox.Resources><wpf:DataResource x:Key="EditTextBoxReturnCommandParameter" BindingTarget="{Binding Path=Content, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}}"/> <wpf:DataResource x:Key="EditTextBoxEscapeCommandParameter" BindingTarget="{Binding ElementName=editFileNameTextBox}"/> </TextBox.Resources> <TextBox.InputBindings> <KeyBinding Key="Return" CommandParameter="{StaticResource EditTextBoxReturnCommandParameter}" Command="{StaticResource EditTextBoxReturnCommand}"/> <KeyBinding Key="Escape" CommandParameter="{StaticResource EditTextBoxEscapeCommandParameter}" Command="{StaticResource EditTextBoxEscapeCommand}"/> </TextBox.InputBindings>?
.net 4.0的兼容性問題
1. 不支持在Xaml有嵌套的template
<ListBox ItemsSource="{Binding Mylist}"><ListBox.ItemTemplate><DataTemplate><ListBox ItemsSource="{Binding}"><ListBox.ItemTemplate><DataTemplate><TextBlock Text="{Binding}" Loaded="TextBlock_Loaded" Style="{StaticResource TextBlockStyle}" /></DataTemplate></ListBox.ItemTemplate></ListBox></DataTemplate></ListBox.ItemTemplate> </ListBox>解決方案
1. Add the datatemplate as a StaticResource reference
<ListBox ItemsSource="{Binding Mylist}"> <ListBox.ItemTemplate> <DataTemplate> <DataTemplate.Resources> <DataTemplate x:Key="nestedDataTemplate"> <TextBlock Text="{Binding}" Loaded="TextBlock_Loaded" Style="{DynamicResource TextBlockStyle}" /> </DataTemplate> </DataTemplate.Resources> <ListBox ItemsSource="{Binding}" ItemTemplate="{StaticResource nestedDataTemplate}"/> </DataTemplate> </ListBox.ItemTemplate> </ListBox>2. Use DynamicResource for the style
<TextBlock Text="{Binding}" Loaded="TextBlock_Loaded" Style="{DynamicResource TextBlockStyle}" />https://social.msdn.microsoft.com/Forums/vstudio/en-US/629bfcc5-2005-4947-a001-993524798b52/istyleconnectorconnect-nullreferenceexception-was-unhandled-in-datatamplate-framework-40?forum=wpf?
http://support.microsoft.com/kb/2464222
轉載于:https://www.cnblogs.com/trent-xu/p/6597602.html
總結
以上是生活随笔為你收集整理的WPF在不同.Net版本间的兼容性问题的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: install maven3 on ub
 - 下一篇: 基于Vue实现后台系统权限控制