当前位置: 首页 > news >正文

做网站优化推广免费关键词排名优化

做网站优化推广,免费关键词排名优化,山西省吕梁市疫情,兰州网络推广做啥的引言 最近因为一个触发器设置的结果总是不起效果的原因,进一步去了解[依赖属性的优先级](Dependency property value precedence - WPF .NET | Microsoft Learn)。在学习这个的过程中发现对SetCurrentValue一直以来的谬误。 在WPF中依赖属性Dependency property的…

引言

最近因为一个触发器设置的结果总是不起效果的原因,进一步去了解[依赖属性的优先级](Dependency property value precedence - WPF .NET | Microsoft Learn)。在学习这个的过程中发现对SetCurrentValue一直以来的谬误。

在WPF中依赖属性Dependency property的三个方法SetValue 、SetCurrentValue、ClearValue。

  1. SetCurrentValue 方法用于设置依赖属性的当前值,但不会覆盖该属性的值来源。这意味着,如果属性值是通过绑定、样式或触发器设置的,使用 SetCurrentValue 后,这些设置仍然有效。

然而这很容易让人以为SetValue 方法会使得数据绑定失效。就像先执行了ClearValue 一样。网上我看到的很多文章也这么说,这让我困惑了很久,但我实际操作下来,并非如此,实际上并不是。

为了验证这三个方法,我以设置按钮背景颜色为例,写了一个Demo。

其主要作用如下:

1. myButton绑定默认背景颜色的依赖属性
<Buttonx:Name="MyButton"Width="100"Height="50"Background="{Binding DefaultBackgroundColor,Mode=TwoWay,RelativeSource={RelativeSource AncestorType={x:Type local:MainWindow}}}"Content="MyButton" />
 public static readonly DependencyProperty DefaultBackgroundColorProperty =DependencyProperty.Register("DefaultBackgroundColor",typeof(Brush),typeof(MainWindow),new PropertyMetadata(Brushes.Pink,OnDefaultBackgroundColorChanged));private static void OnDefaultBackgroundColorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){MessageBox.Show("DefaultBackgroundColor changed");}public static readonly DependencyProperty DefaultForegroundColorProperty =DependencyProperty.Register("DefaultForegroundColor",typeof(Brush),typeof(MainWindow),new PropertyMetadata(Brushes.Gray,OnDefaultForegroundChanged));
2. 按钮1使用SetValue设置myButton的背景颜色属性,并判断绑定表达式是否为空
  private void SetValueChangeBackground_Click(object sender, RoutedEventArgs e){MyButton.SetValue(Button.BackgroundProperty, new SolidColorBrush(Colors.Green));IsBindingExpressionNull();}private void IsBindingExpressionNull()
{ if (MyButton.GetBindingExpression(Button.BackgroundProperty) == null){MessageBox.Show("BindingExpression is null");}
}
3. 按钮2使用SetCurrentValue设置myButton的背景颜色属性
 MyButton.SetCurrentValue(Button.BackgroundProperty, new SolidColorBrush(Colors.Orange));
IsBindingExpressionNull();
4. 按钮3 使用ClearValue 清楚背景颜色属性本地值
 // 清除本地值MyButton.ClearValue(Button.BackgroundProperty);
IsBindingExpressionNull();
5. 按钮4,修改依赖属性
DefaultBackgroundColor = new SolidColorBrush(Colors.LightGreen);
我使用.NET 8 做的Demo的现象如下:
  1. ClearValue执行后,绑定表达式为Null,也就是说ClearValue之后,绑定的数据表达式会被清空
  2. SetValue执行后,按钮颜色正常改变,绑定表达式不为Null。再次执行按钮4 修改依赖属性,按钮背景颜色也可以正常变化,也就是说SetValue之后数据表达式不会被清空,仍然有效。
  3. SetCurrentValue与第2点现象完全一致。

源码

通过查看源码,发现SetCurrentValueSetValue都执行方法SetValueCommon,只是入参coerceWithCurrentValue不同,// SetValue时为false 和SetCurrentValue时为true。

并且推测当SetValue的value入参等于DependencyProperty.UnsetValue时,应当会和ClearValueCommon执行相同的方法。

以下是测试代码,实际测试结果也是如此,此时绑定表达式为Null。

private void SetValueChangeBackgroundUnsetValue_Click(object sender, RoutedEventArgs e){MyButton.SetValue(Button.BackgroundProperty, DependencyProperty.UnsetValue);  //查看源码发现,UnsetValue时才会是清除本地值,并且 ClearValueIsBindingExpressionNull();}
SetValueCommon
        /// <summary>///     The common code shared by all variants of SetValue/// </summary>// Takes metadata from caller because most of them have already retrieved it//  for their own purposes, avoiding the duplicate GetMetadata call.private void SetValueCommon(DependencyProperty  dp,object              value,PropertyMetadata    metadata,bool                coerceWithDeferredReference,bool                coerceWithCurrentValue, // SetValue时为false 和SetCurrentValue时为trueOperationType       operationType,bool                isInternal){if (IsSealed){throw new InvalidOperationException(SR.Get(SRID.SetOnReadOnlyObjectNotAllowed, this));}Expression newExpr = null;DependencySource[] newSources = null;EntryIndex entryIndex = LookupEntry(dp.GlobalIndex);// Treat Unset as a Clearif( value == DependencyProperty.UnsetValue ){Debug.Assert(!coerceWithCurrentValue, "Don't call SetCurrentValue with UnsetValue");// Parameters should have already been validated, so we call//  into the private method to avoid validating again.ClearValueCommon(entryIndex, dp, metadata);return;}// Validate the "value" against the DP.bool isDeferredReference = false;bool newValueHasExpressionMarker = (value == ExpressionInAlternativeStore);// First try to validate the value; only after this validation fails should we// do the more expensive checks (type checks) for the less common scenariosif (!newValueHasExpressionMarker){bool isValidValue = isInternal ? dp.IsValidValueInternal(value) : dp.IsValidValue(value);// for properties of type "object", we have to always check for expression & deferredreferenceif (!isValidValue || dp.IsObjectType){// 2nd most common is expressionnewExpr = value as Expression;if (newExpr != null){// For Expressions, perform additional validation// Make sure Expression is "attachable"if (!newExpr.Attachable){throw new ArgumentException(SR.Get(SRID.SharingNonSharableExpression));}// Check dispatchers of all Sources// CALLBACKnewSources = newExpr.GetSources();ValidateSources(this, newSources, newExpr);}else{// and least common is DeferredReferenceisDeferredReference = (value is DeferredReference);if (!isDeferredReference){if (!isValidValue){// it's not a valid value & it's not an expression, so throwthrow new ArgumentException(SR.Get(SRID.InvalidPropertyValue, value, dp.Name));}}}}}// Get old valueEffectiveValueEntry oldEntry;if (operationType == OperationType.ChangeMutableDefaultValue){oldEntry = new EffectiveValueEntry(dp, BaseValueSourceInternal.Default);oldEntry.Value = value;}else{oldEntry = GetValueEntry(entryIndex, dp, metadata, RequestFlags.RawEntry);}// if there's an expression in some other store, fetch it nowExpression currentExpr =(oldEntry.HasExpressionMarker)  ? _getExpressionCore(this, dp, metadata): (oldEntry.IsExpression)         ? (oldEntry.LocalValue as Expression):                                   null;// Allow expression to store value if new value is// not an Expression, if applicablebool handled = false;if ((currentExpr != null) && (newExpr == null)){// Resolve deferred references because we haven't modified// the expression code to work with DeferredReference yet.if (isDeferredReference){value = ((DeferredReference) value).GetValue(BaseValueSourceInternal.Local);}// CALLBACKhandled = currentExpr.SetValue(this, dp, value);entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex);}// Create the new effective value entryEffectiveValueEntry newEntry;if (handled)                                                                                                                                                                                        ){// If expression handled set, then doneif (entryIndex.Found){newEntry = _effectiveValues[entryIndex.Index];}else{// the expression.SetValue resulted in this value being removed from the table;// use the default value.newEntry = EffectiveValueEntry.CreateDefaultValueEntry(dp, metadata.GetDefaultValue(this, dp));}coerceWithCurrentValue = false; // expression already handled the control-value}else{// allow a control-value to coerce an expression value, when the// expression didn't handle the valueif (coerceWithCurrentValue && currentExpr != null){currentExpr = null;}newEntry = new EffectiveValueEntry(dp, BaseValueSourceInternal.Local);// detach the old expression, if applicableif (currentExpr != null){// CALLBACKDependencySource[] currentSources = currentExpr.GetSources();UpdateSourceDependentLists(this, dp, currentSources, currentExpr, false);  // Remove// CALLBACKcurrentExpr.OnDetach(this, dp);currentExpr.MarkDetached();entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex);}// attach the new expression, if applicableif (newExpr == null){// simple local value setnewEntry.HasExpressionMarker = newValueHasExpressionMarker;newEntry.Value = value;}else{Debug.Assert(!coerceWithCurrentValue, "Expression values not supported in SetCurrentValue");// First put the expression in the effectivevalueentry table for this object;// this allows the expression to update the value accordingly in OnAttachSetEffectiveValue(entryIndex, dp, dp.GlobalIndex, metadata, newExpr, BaseValueSourceInternal.Local);// Before the expression is attached it has default valueobject defaultValue = metadata.GetDefaultValue(this, dp);entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex);SetExpressionValue(entryIndex, defaultValue, newExpr);UpdateSourceDependentLists(this, dp, newSources, newExpr, true);  // AddnewExpr.MarkAttached();// CALLBACKnewExpr.OnAttach(this, dp);// the attach may have added entries in the effective value table ...// so, update the entryIndex accordingly.entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex);newEntry = EvaluateExpression(entryIndex,dp,newExpr,metadata,oldEntry,_effectiveValues[entryIndex.Index]);entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex);}}UpdateEffectiveValue(entryIndex,dp,metadata,oldEntry,ref newEntry,coerceWithDeferredReference,coerceWithCurrentValue,operationType);}
ClearValueCommon
/// <summary>///     The common code shared by all variants of ClearValue/// </summary>private void ClearValueCommon(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata){if (IsSealed){throw new InvalidOperationException(SR.Get(SRID.ClearOnReadOnlyObjectNotAllowed, this));}// Get old valueEffectiveValueEntry oldEntry = GetValueEntry(entryIndex,dp,metadata,RequestFlags.RawEntry);// Get current local value// (No need to go through read local callback, just checking// for presence of Expression)object current = oldEntry.LocalValue;// Get current expressionExpression currentExpr = (oldEntry.IsExpression) ? (current as Expression) : null;// Inform value expression of detachment, if applicableif (currentExpr != null){// CALLBACKDependencySource[] currentSources = currentExpr.GetSources();UpdateSourceDependentLists(this, dp, currentSources, currentExpr, false);  // Remove// CALLBACKcurrentExpr.OnDetach(this, dp);currentExpr.MarkDetached();entryIndex = CheckEntryIndex(entryIndex, dp.GlobalIndex);}// valuesource == Local && value == UnsetValue indicates that we are clearing the local valueEffectiveValueEntry newEntry = new EffectiveValueEntry(dp, BaseValueSourceInternal.Local);// Property is now invalidUpdateEffectiveValue(entryIndex,dp,metadata,oldEntry,ref newEntry,false /* coerceWithDeferredReference */,false /* coerceWithCurrentValue */,OperationType.Unknown);}

Mode对SetValue的影响

在wpf - 依赖属性SetValue()和SetCurrentValue()之间的区别是什么 - 堆栈溢出 — wpf - What’s the difference between Dependency Property SetValue() & SetCurrentValue() - Stack Overflow上看到和Mode还有关系,于是我又测试了一下:
在这里插入图片描述

将按钮的绑定方式改为OneWay,发现SetValue执行后,绑定为Null,绑定被销毁。

<Buttonx:Name="MyButton"Width="100"Height="50"Background="{Binding DefaultBackgroundColor,Mode=OneWay,RelativeSource={RelativeSource AncestorType={x:Type local:MainWindow}}}"Content="MyButton" />

总结

就我的测试Demo来看,

  1. ClearValue会使得数据绑定失效。
  2. SetCurrentValue和官方文档所述一致,不会覆盖该属性的值来源,如果属性值是通过绑定、样式或触发器设置的,使用 SetCurrentValue 后,这些设置仍然有效。
  3. SetValue 设置的依赖属性为DependencyProperty.UnsetValue,会和ClearValue的表现一致。
  4. SetValue在Mode=TwoWay时,和SetCurrentValue表现一致,数据绑定不会失效。
  5. SetValue 在Mode=OneWay时。数据绑定也会失效。

参考

  1. What’s the difference between Dependency Property SetValue() & SetCurrentValue()
  2. Dependency property value precedence - WPF .NET | Microsoft Learn
  3. 源码
http://www.dt0577.cn/news/28477.html

相关文章:

  • 万网建站教程google应用商店
  • 做网站的上海公司有哪些百度seo怎么把关键词优化上去
  • 在深圳做网站多少钱百度关键词优化推广
  • 温州高端网站建设自己有网站怎么推广
  • 网站域名有哪些网站seo排名免费咨询
  • 云南网站开发网络公司谷歌推广网站
  • 安居网站建设sem培训班学费哪个好
  • 外贸网站建设外seo如何优化网站推广
  • 教外国人做中国菜网站百度关键字优化
  • 网站建设 顺德seo排名优化软件
  • 网站制作实验报告百度问答我要提问
  • wordpress 跳转链接地址百度seo怎么样优化
  • 网站站内文章互联店铺推广怎么做
  • 企业建设网站个人总结网络营销培训机构
  • 网站做查赚钱百度搜索下载
  • 日照网站建设游戏代理平台一天结一次
  • 灯具电商网站建设方案游戏搬砖工作室加盟平台
  • 校园官方网站建设如何推广自己成为网红
  • c2c电子商务网站建设栏目结构图网页设计一般用什么软件
  • 大连网站建设功能的网站建设
  • 南宁做网站比较好的公司外贸商城建站
  • 济南网站建设大标网络推广公司
  • 揭阳网站开发mituad推推蛙贴吧优化
  • 色流网站怎么做网站建设技术外包
  • 设计网站卖钱奶茶网络营销策划方案
  • wordpress 主题开发环境seo网络推广是干嘛的
  • 网站开发文案武汉seo排名扣费
  • 潮流设计网站360站长平台
  • 做公司官网需要什么条件优化网络培训
  • 网络营销的理论有哪些seo网站推广是什么