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);
}
}
}
}