WPF经验笔记

Grid使用

  • 在Grid中使用Microsoft.Xaml.Behavior中的Trigger时,必须设置Grid的BackGround值,否则不能在Grid的整片区域有效

Style使用

  • 当采用样式与界面分离时,在DataTemplate的Trigger中,使用DataTrigger绑定到自定义的附加数值时,若出现修改附加属性值没有触发DataTrigger现象,则将该Style或DataTemplate直接写在控件中而不是样式与界面分离。

GridSplitter使用

  • 使用GridSplitter后可以在设置如何设置各个区域的默认宽度?
    在ColumnDefinition或RowDefinition上直接设置数值即可。
   <Grid>
       <Grid.ColumnDefinitions>
           <ColumnDefinition Width="400"/><!--设置默认宽度-->
           <ColumnDefinition Width="2"/>
           <ColumnDefinition Width="1*"/>
       </Grid.ColumnDefinitions>
       <Grid Grid.Column="0">
           
       </Grid>
       <GridSplitter Grid.Column="1" Width="2" VerticalAlignment="Stretch"/>
       <Grid Grid.Column="2">
           
       </Grid>
   </Grid>

DataGrid使用

  • DataGrid布局
    1.DataGrid自适应宽度时,若DataGrid所在容器(如Grid)宽度为Auto时,可通过设置每个DataGridColumn的最小列宽MinWidth来设置。

  • DatagridRow
    1.DataGridRow是UI类型控件可设置样式,但DataGridColumn没有
    2.大量数据绑定时设置DataGridRow的Visibility会破坏DataGrid的虚拟化
    3.若DataGrid放在一个自动扩展的容器中不会虚拟化,如StackPanel;可以改为放在Grid中。

  • SelectiveScrollingGrid
    SelectiveScrollingOrientation是一个其一个附加属性,可设置元素是是否可以在垂直方向或水平方向滚动,对应的设置代码如下:

        /// <summary>
        /// Property changed call back for SelectiveScrollin----entation property
        /// </summary>
        /// <param name="d"></param>
        /// <param name="e"></param>
        private static void OnSelectiveScrollingOrientationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            UIElement element = d as UIElement;
            SelectiveScrollingOrientation orientation = (SelectiveScrollingOrientation)e.NewValue;
            ScrollViewer scrollViewer = DataGridHelper.FindVisualParent<ScrollViewer>(element);
            if (scrollViewer != null && element != null)
            {
                Transform transform = element.RenderTransform;
 
                if (transform != null)
                {
                    BindingOperations.ClearBinding(transform, TranslateTransform.XProperty);
                    BindingOperations.ClearBinding(transform, TranslateTransform.YProperty);
                }
 
                if (orientation == SelectiveScrollingOrientation.Both)
                {
                    element.RenderTransform = null;
                }
                else
                {
                    TranslateTransform translateTransform = new TranslateTransform();
 
                    // Add binding to XProperty of transform if orientation is not horizontal
                    if (orientation != SelectiveScrollingOrientation.Horizontal)
                    {
                        Binding horizontalBinding = new Binding("ContentHorizontalOffset");
                        horizontalBinding.Source = scrollViewer;
                        BindingOperations.SetBinding(translateTransform, TranslateTransform.XProperty, horizontalBinding);
                    }
 
                    // Add binding to YProperty of transfrom if orientation is not vertical
                    if (orientation != SelectiveScrollingOrientation.Vertical)
                    {
                        Binding verticalBinding = new Binding("ContentVerticalOffset");
                        verticalBinding.Source = scrollViewer;
                        BindingOperations.SetBinding(translateTransform, TranslateTransform.YProperty, verticalBinding);
                    }
 
                    element.RenderTransform = translateTransform;
                }
            }
        }

Popup使用

  • Popup只有在属性AllowsTransparency设置为True时动画才有效果
  • 通过Placement和PlacementTarget可以控制显示位置
  • 通过VerticalOffset和HorizontalOffset可以控制偏移量
  • 在Popup里面的控件通过视图树无法找到Popup控件,VisualHelper通过InternalVisualParent获取视图树父节点;在AddVisualChild方法中对子节点的InternalVisualParent赋值;Popup是通过AddLogicalChild添加子节点,所以与其Child(PopupRoot)只在逻辑树上建立了关系,并不能通过视图树找到Popup:

VisualTreeHelper的GetParent代码:

 /// <summary>
 /// Visual parent of this Visual.
 /// </summary>
 public static DependencyObject GetParent(DependencyObject reference)
 {
     Visual visual;
     Visual3D visual3D;

     VisualTreeUtils.AsNonNullVisual(reference, out visual, out visual3D);

     // x86 branch prediction skips the branch on first encounter.  We favor 2D.
     if (visual3D != null)
     {
         return visual3D.InternalVisualParent;
     }

     return visual.InternalVisualParent;
 }

正常建立视图树关系:

 protected void AddVisualChild(Visual child)
 {
     if (child == null)
     {
         return;
     }

     if (child._parent != null)
     {
         throw new ArgumentException(SR.Get(SRID.Visual_HasParent));
     }

     // invalid during a VisualTreeChanged event
     VisualDiagnostics.VerifyVisualTreeChange(this);

     SetFlags(true, VisualFlags.HasChildren);

     // Set the parent pointer.

     child._parent = this;//建立视图树关系

	 //其他代码
	 ...........
 }

Visual类的InternalVisualParent属性:

 /// <summary>
 /// Identical to VisualParent, except that skips verify access for perf.
 /// </summary>
 internal DependencyObject InternalVisualParent
 {
     get
     {
         return _parent;
     }
 }

Popup通过OnIsOpenChanged事件->调用CreateWindow方法->CreatePopupRoot方法创建PopupRoot并在将Popup内容赋值给PopupRoot对象的Child,建立的逻辑树:

  /// <SecurityNote>
   ///     Critical: Sets rootvisual from popuproot
   ///     TreatAsSafe: It initializes this to new value of the popuproot and
   ///     this should not cause any untowards behavior since it is not configurable
   /// </SecurityNote>
   [SecurityCritical,SecurityTreatAsSafe]
   private void CreateNewPopupRoot()
   {
       if (_popupRoot.Value == null)
       {
       	   //创建新对象并添加到逻辑树
           _popupRoot.Value = new PopupRoot();
           AddLogicalChild(_popupRoot.Value);
           // Allow users to set Width/Height properties on the Popup and have them
           // apply to the content.
           _popupRoot.Value.SetupLayoutBindings(this);
       }
   }
  /// <summary>
  ///     The DependencyProperty for the Child property.
  ///     Flags:              None
  ///     Default Value:      null
  /// </summary>
  public static readonly DependencyProperty ChildProperty =
          DependencyProperty.Register(
                  "Child",
                  typeof(UIElement),
                  typeof(Popup),
                  new FrameworkPropertyMetadata(
                          (object) null,
                          new PropertyChangedCallback(OnChildChanged)));

  /// <summary>
  ///     The content of the Popup
  /// </summary>
  [Bindable(true), CustomCategory("Content")]
  public UIElement Child
  {
      get { return (UIElement) GetValue(ChildProperty); }
      set { SetValue(ChildProperty, value); }
  }

  private static void OnChildChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  {
      Popup popup = (Popup)d;

      UIElement oldChild = (UIElement) e.OldValue;
      UIElement newChild = (UIElement) e.NewValue;

      // If the Popup is open, change the PopupRoot's child to show the new content.
      // Also change if the PopupRoot has a non-null child, to enable that
      // child to participate elsewhere in the visual tree (DDVSO 161345).
      if ((popup._popupRoot.Value != null) && (popup.IsOpen || popup._popupRoot.Value.Child != null))
      {
          popup._popupRoot.Value.Child = newChild;
      }

      popup.RemoveLogicalChild(oldChild);

      popup.AddLogicalChild(newChild);//添加到逻辑树
      popup.Reposition();

      popup.pushTextRenderingMode();
  }

添加到逻辑树方法:

   protected internal void AddLogicalChild(object child)
   {
       if (child != null)
       {
           // It is invalid to modify the children collection that we
           // might be iterating during a property invalidation tree walk.
           if (IsLogicalChildrenIterationInProgress)
           {
               throw new InvalidOperationException(SR.Get(SRID.CannotModifyLogicalChildrenDuringTreeWalk));
           }

           // Now that the child is going to be added, the FE/FCE construction is considered finished,
           // so we do not expect a change of InheritanceBehavior property,
           // so we can pick up properties from styles and resources.
           TryFireInitialized();

           bool exceptionThrown = true;
           try
           {
               HasLogicalChildren = true;

               // Child is present; reparent him to this element
               FrameworkObject fo = new FrameworkObject(child as DependencyObject);
               fo.ChangeLogicalParent(this);

               exceptionThrown = false;
           }
           finally
           {
               if (exceptionThrown)
               {
                   // 


                   // Consider doing this...
                   //RemoveLogicalChild(child);
               }
           }
       }
   }

持续更新…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值