locked
WPF 精华问答集中帖 RRS feed

全部回复

  •  1.1. WPF 4 有哪些新控件

    WPF 4新增发布了WPF Toolkit的三个控件:他们是DataGrid,DatePicker,Calendar.这三个控件使得大家开发商业应用程序更加简单,同时他们几乎100%的兼容了Silverlight中的这些控件。 (Silverlight:DataGrid,DatePicker,Calendar.

    WindowsClient.net中,有两篇介绍这三个控件是如何在WPF 4的下工作的演示文档,大家可以参考.

    ·    DataGrid:http://windowsclient.net/wpf/wpf35/wpf-35sp1-toolkit-datagrid-feature-walkthrough.aspx

    ·    DatePicker and Calendar:http://windowsclient.net/wpf/wpf35/wpf-35sp1-toolkit-calendar-datepicker-walkthrough.aspx#getstarted

    同时,我们可以列出一起其他深入讨论如何使用这些控件的文章,大家可以参考下面的链接:

    ·    DataGrid blogs inVincent Sibal's Blog:http://blogs.msdn.com/b/vinsibal/archive/tags/datagrid/

    ·    From Codeproject.com: Colin Eberhardt - WPF DataGrid Practical Examples:http://www.codeproject.com/KB/WPF/WPFDataGridExamples.aspx

    ·    FromMSDN Magazine: Charles Petzold - Customizing the New WPF Calendar Controls: http://msdn.microsoft.com/zh-cn/magazine/dd882520.aspx


    Sheldon _Xiao[MSFT]
    MSDN Community Support | Feedback to us
    Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2012年4月17日 3:48
    版主
  • 1.2. 如何从 Datagrid 中获得单元格的内容

    DataGrid属于一种 ItemsControl,因此,它有 Items属性并且用ItemContainer封装它的 items.但是,WPF中的DataGrid不同于Windows Forms中的DataGridViewDataGridItems集合中,DataGridRow是一个Item,但是,它里面的单元格却是被封装在DataGridCellsPresenter的容器中;因此,我们不能使用像DataGridView.Rows.Cells这样的语句去获得单元格的内容。但是,在WPF中我们可以通过可视树(VisualTree)去进入到控件“内部“,那么,我们当然可以通过VisualTree进入DataGrid中的DataGridRowDataGridCellsPresenter,并且得到在DataGridCellsPresenter中的实例,大家可以通过以下的代码遍历VisualTree

    DataGridRow rowContainer = (DataGridRow)dataGrid1.ItemContainerGenerator.ContainerFromIndex(rowIndex);

    DataGridCellsPresenter presenter = GetVisualChild(rowContainer);

    DataGridCell cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(columnIndex);

    // ...

    publicstatic T GetVisualChild<T>(Visual parent)where T : Visual

    {

    T child = default(T);

    int numVisuals = VisualTreeHelper.GetChildrenCount(parent);

    for (int i = 0; i < numVisuals; i++)

    {

       Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);

       child = v as T;

      

       if (child ==null)

         child = GetVisualChild(v);

       else

         break;

    }

    return child;

    }


    Sheldon _Xiao[MSFT]
    MSDN Community Support | Feedback to us
    Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2012年4月17日 3:48
    版主
  • 2.1. 如何去理解 WPF 4 中的 Visual State Manager (VSM)

    Visual State这个概念最初是在 Silverlight中发布的, 后来在WPF Toolkit中又一次被提到,Microsoft Expression Blend 2.5 以后的版本也支持使用 Visual State Manager开发样式/模板.WPF4中发布了Visual State Manager,用户可以在WPF控件模板中的设置Visual States并且可以根据不同的条件去转换Visual States.Visual State Manager类就像模板中的触发器(Trigger),但是它能够更加有条理的组织States这个属性,而且通过VisualTransition这个类进行States转化也更加容易。

    相关的文档:

    ·    WindowsClient.net - WPF Toolkit: Visual State Manager Overview:http://windowsclient.net/wpf/wpf35/wpf-35sp1-toolkit-visual-state-manager-overview.aspx

    ·    Silverlight.net - Styles, Templates and Visual State Manager:http://www.silverlight.net/learn/tutorials/stylestemplatesvsm-cs/

    ·    Expression Blend and Design blog - Visual state manager tips for design and authoring: http://blogs.msdn.com/b/expression/archive/2009/10/02/visual-state-manager-tips-for-design-and-authoring.aspx


    Sheldon _Xiao[MSFT]
    MSDN Community Support | Feedback to us
    Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2012年4月17日 3:49
    版主
  • 2.2. 什么是 Visual State Manager?我们如何用代码使用 VSM去控制 VisualState

    VisualStateManager控制控件的状态(states)逻辑之间的转化.同时, VisualStateManager也使用户可以根据不同的states为控件指定不同的外观.例如,一个Button在按下的states和没有被按下的时候可以有不同的外观。这样,你就可以为Button指定2states,一个是(“按下”),另一个是(“正常”).我们可以通过VisualState去控制一个特性states下的控件外观.一个VisualState中包含 Storyboard对象的集合,这些集合可以指定当一个空间在某一状态下的外观.我们可以为一个控件添加visual states通过设置控件的附加属性,这个属性是: VisualStateManager.VisualStateGroups.每一个VisualStateGroup包含自己特有的VisualState对象的集合。这就说明在某一VisualStateGroup中的states,总是会显示正常的.


    在下面的例子中,我们可以通过 VisualStateManager.GoToElementState VisualStateManager.GoToState在两个不同的states中进行转化,并且通过GetVisualStateGroups去得到VisualStateManager.VisualStateGroups附加属性.在下面的示例中,两个Buttons能够在“Normal”和“Waning”两个状态中进行转换:

    XAML:

    <StackPanel>

    <EllipseName="ellipse"Width="100"Height="100"Fill="Green">

    <VisualStateManager.VisualStateGroups>

      <VisualStateGroupName="CommonStates">

       <VisualStateName="Normal"/>

       <VisualStateName="Warning">

        <Storyboard>

         <ColorAnimationTo="Red"Storyboard.TargetName="ellipse"Storyboard.TargetProperty="Fill.Color"/>

        </Storyboard>

       </VisualState>

       <VisualStateGroup.Transitions>

        <VisualTransitionTo="Normal"GeneratedDuration="00:00:01"/>

        <VisualTransitionTo="MouseOver"GeneratedDuration="00:00:01"/>

       </VisualStateGroup.Transitions>

      </VisualStateGroup>

    </VisualStateManager.VisualStateGroups>

    </Ellipse>

    <StackPanelOrientation="Horizontal"HorizontalAlignment="Center">

    <ButtonName="buttonNormal"Content="Normal"Click="Normal_Click"Margin="2"/>

    <ButtonName="buttonWarning"Content="Warning"Click="Warning_Click"Margin="2"/>

    </StackPanel>

    </StackPanel>

    C#代码:

    privatevoid Normal_Click(object sender, RoutedEventArgs e)

    {

    VisualStateManager.GoToElementState(ellipse, "Normal",true);

    }

    privatevoid Warning_Click(object sender, RoutedEventArgs e)

    {

    VisualStateManager.GoToElementState(ellipse, "Warning",true);

    }


    Sheldon _Xiao[MSFT]
    MSDN Community Support | Feedback to us
    Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2012年4月17日 3:50
    版主
  • 3.1. 如何在 WPF 4 中使用触控和操作?

    WPF 4,我们有基本的触摸事件供我们使用:TouchDownEvent,TouchEnterEvent,TouchLeaveEvent,TouchMoveEvent,TouchUpEvent.并且这些触摸事件支持 UIElement, UIElement3D ContentElement.因此我们可以处理这些事件去描绘形状和元素,或者在代码中使用特殊的操作实现多点触摸.

    一个简单的示例:

    XAML:

    <Canvasx:Name="canvas"

       TouchDown="canvas_TouchDown"

       TouchMove="canvas_TouchMove"

       TouchUp="canvas_TouchUp"/>

    Code:

    public MainWindow()

    {

    InitializeComponent();

    shapes = new Dictionary();

    }

    privatevoid canvas_TouchDown(object sender, TouchEventArgs e)

    {

    var shape = CreateShape();

    var origin = e.GetTouchPoint(canvas);

    shape.RenderTransform = new TranslateTransform(origin.Position.X - shape.RenderSize.Width / 2,

    origin.Position.Y - shape.RenderSize.Height / 2);

    shapes.Add(e.TouchDevice, shape);

    // Add the shape to the canvas

    canvas.Children.Add(shape);

    canvas.InvalidateVisual();

    canvas.CaptureTouch(e.TouchDevice);

    }

    privatevoid _canvas_TouchMove(object sender, TouchEventArgs e)

    {

    if (e.TouchDevice.Captured == canvas)

    {

       var shape = shapes[e.TouchDevice];

       var origin = e.GetTouchPoint(canvas);

       shape.RenderTransform = new TranslateTransform(origin.Position.X - shape.RenderSize.Width / 2,

      origin.Position.Y - shape.RenderSize.Height / 2);

    }

    }

    privatevoid canvas_TouchUp(object sender, TouchEventArgs e)

    {

    canvas.ReleaseTouchCapture(e.TouchDevice);

    canvas.Children.Remove(shapes[e.TouchDevice]);

    shapes.Remove(e.TouchDevice);

    }

    对于操作,我们可以对ManipulationStarted, ManipulationDelta, ManipulationStarting, ManipulationCompleted 事件进行处理,然后通过处理ManipulationDelta事件去响应由手指移动所产生的变化。这里有一个来自于Anson Tsao的博客文章的简单样例

    XAML:

    <Canvasx:Name="_canvas"  

       ManipulationStarting="_canvas_ManipulationStarting"  

       ManipulationDelta="_canvas_ManipulationDelta">

    <RectangleIsManipulationEnabled="True"Fill="Red"Width="100"Height="100"/>

    </Canvas>

    Code:

    privatevoid _canvas_ManipulationStarting(object sender, ManipulationStartingEventArgs e)

    {

    e.ManipulationContainer = _canvas;

    e.Handled = true;

    }

    privatevoid _canvas_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)

    {

    var element = e.OriginalSourceas UIElement;

    var transformation = element.RenderTransformas MatrixTransform;

    var matrix = transformation ==null Matrix.Identity : transformation.Matrix;

    matrix.ScaleAt(e.DeltaManipulation.Scale.X,

             e.DeltaManipulation.Scale.Y,

             e.ManipulationOrigin.X,

             e.ManipulationOrigin.Y);

    matrix.RotateAt(e.DeltaManipulation.Rotation,

             e.ManipulationOrigin.X,

             e.ManipulationOrigin.Y);

    matrix.Translate(e.DeltaManipulation.Translation.X,

              e.DeltaManipulation.Translation.Y);

    element.RenderTransform = new MatrixTransform(matrix);

    e.Handled = true;

    }

    大家可以参考如下资源以获取更多信息:

    ·    MDSN示例 -创建您的第一个触控应用程序http://msdn.microsoft.com/zh-cn/library/ee649090.aspx

    ·    Jaime Rodriguez's的博客介绍WPF4的多点触摸:http://blogs.msdn.com/b/jaimer/archive/2009/11/04/introduction-to-wpf-4-multitouch.aspx

    ·    Anson Tsao's的博客介绍WPF 4的多点触摸:http://blogs.msdn.com/b/ansont/archive/tags/multitouch/


    Sheldon _Xiao[MSFT]
    MSDN Community Support | Feedback to us
    Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2012年4月17日 3:52
    版主
  • 3.2. 如何在 WPF 4 中使用手势?

    答案是否定的, WPF 4支持多点触摸和操作,但是不支持手势.所以我们必须编写一个自定义的GestureHandler程序集并且添加这个程序集的引用到WPF 4的工程中以使WPF 4支持手势。请参考Windows 7 Multitouch .NET Interop Sample Library以建立一个支持手势的程序集。以下资源是关于在Windows 7环境下开发多点触摸程序的:


    相关资源:http://social.msdn.microsoft.com/Forums/zh-cn/wpf/thread/18695b90-1819-41c4-bbac-277ac2642ec5


    Sheldon _Xiao[MSFT]
    MSDN Community Support | Feedback to us
    Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2012年4月17日 3:52
    版主
  •  4.1. 什么是布局舍入以及如何在 WPF 4 中使用?

    当物体的边缘处于一个像素设备的中间时,DPI独立的图形系统会产生伪影,如模糊或者半透明边缘。之前版本的WPF包含像素捕捉功能来帮助解决这个问题。Silverlight 2引入了布局舍入,这是另外一种移动元素以使边缘落在整个像素边界的方法。WPF现在支持FrameworkElement附加属性UseLayoutRounding的边界舍入。在像素边界描绘物体可以消除当物体的边缘处于一个像素设备的中间时由伪影产生的半透明边缘。当你使用布局舍入时,布局系统在行列测量时产生微小的偏差以消除子像素渲染。

    下列代码使用UseLayoutRounding附加属性设置一个单像素宽的直线。当你缓慢改变窗体大小时,你可以看到布局舍入产生的差别。

    <StackPanel Width="150" Margin="7" Orientation="Horizontal">
      <!-- Single pixel line with layout rounding turned OFF.-->
      <Rectangle UseLayoutRounding="False" Width="45.6" Margin="10" Height="1" Fill="Red"/>
      
      <!-- Single pixel line with layout rounding turned ON.-->
      <Rectangle UseLayoutRounding="True" Width="45.6" Margin="10" Height="1" Fill="Red"/>
    </StackPanel>

    Sheldon _Xiao[MSFT]
    MSDN Community Support | Feedback to us
    Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2012年4月17日 3:53
    版主
  • 4.2. BitmapCacheBrush VisualBrush 之间的区别?

    BitmapCacheBrush允许使用缓存内容进行区域描绘。BitmapCacheBrush类似于VisualBrush某些情况我们可以使用BitmapCacheBrush来代替VisualBrush。以下例子使用BitmapCacheBrushVisualBrush描绘了一个矩形:

    <StackPanelOrientation="Horizontal">

    <RectangleWidth="100"Height="25"Margin="10">

    <Rectangle.Fill>

      <VisualBrush>

       <VisualBrush.Visual>

        <StackPanelOrientation="Horizontal">

         <TextBlockText="Hello world!"/>

         <ButtonContent="Button"/>

        </StackPanel>

       </VisualBrush.Visual>

      </VisualBrush>

    </Rectangle.Fill>

    </Rectangle>

    <RectangleWidth="100"Height="25"Margin="10">

    <Rectangle.Fill>

      <BitmapCacheBrush>

       <BitmapCacheBrush.Target>

        <StackPanelOrientation="Horizontal">

         <TextBlockText="Hello world!"/>

         <ButtonContent="Button"/>

        </StackPanel>

       </BitmapCacheBrush.Target>

      <BitmapCacheBrush.BitmapCache>

        <BitmapCacheSnapsToDevicePixels="True"RenderAtScale="2"/>

       </BitmapCacheBrush.BitmapCache>

      </BitmapCacheBrush>

    </Rectangle.Fill>

    </Rectangle>

    </StackPanel>

    但是,BitmapCacheBrush总是从一个目标元素的缓存或者通过BitmapCache属性定义的缓存来渲染并且BitmapCacheBrush类忽略以下位于根Visual的属性:VisualOffsetVisualTransformVisualClipVisualEffectVisualOpacityVisualOpacity。这种行为有别于VisualBrush类。


    Sheldon _Xiao[MSFT]
    MSDN Community Support | Feedback to us
    Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2012年4月17日 3:53
    版主
  • 4.3.什么是Pixel Shader 3以及如何在 WPF 4 中使用?

    WPF 4建立在对ShaderEffect的支持之上,我们可以通过使用Pixel Shader 3来创建自定义的位图效果。Pixel Shader是一种着色器程序,通常在一个图像处理单元中执行。这些程序用来完成像素级的效果处理。微软的DirectX支持着色器。并且从DirectX 9.0c开始支持Pixel Shader Version 3,其在支持的硬件上可以完成更多的效果。

    如果一个有效的Pixel Shader 3着色器在一台具备Pixel Shader 3硬件支持的计算机上装载,这个着色器将被忽略。如果此着色器是无效的,将不会有任何异常被抛出。如果计算机上的显示卡有两个或者更多,那么这个效果取决于性能最低的那个显示卡。Pixel Shader 2.0着色器在软件渲染时运行。如果Pixel Shader 3拥有硬件支持,那么Pixel Shader 3将不会在软件渲染过程中运行。关于Pixel Shader 的更多信息,请参考位于Gamedev.net上的Fundamentals of Pixel Shaders文章:

    http://www.gamedev.net/columns/hardcore/dxshader3/

    WPF 4中,首先我们可以使用一种称为High Level Shading Language (HLSL)的语言通过Pixel Shader 3来创建一个自定义的效果;然后使用Direct3D着色器编译器fxc.exeHLSL代码编译为字节代码,其在运行时被执行。在WPF中创建一个PixelShader来装载字节代码并封装这个效果进一个ShaderEffect类。然后我们可以通过设置UIElementEffect属性来使自定义Pixel Shader生效。

    以下资源可以帮助我们理解更多关于WPF中的Pixel Shader 3 以及 HLSL language:


    Sheldon _Xiao[MSFT]
    MSDN Community Support | Feedback to us
    Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2012年4月17日 3:54
    版主
  • 4.4. 如何在动画中创建和使用缓动函数?

    缓动函数(Easing Function)可以让你用数学公式控制动画,这样就可以实现加速以及减速效果,或者向动画添加特殊效果,比如弹跳效果。

    这篇Maxime Lamure的博客Add easing effects on your animations with WPF 4 easing functions向我们演示了如何使用缓动函数。

    Pete Brown
    的文章Introduction to Easing Functions in WPF 4带领我们学习了使用缓动函数的基础知识。

    WPF 4拥有11个内置的缓动函数,它们存在于Sytem.Windows.Media.Animation命名空间中。你可以在这里找到一个缓动函数的列表。

    继承自EasingFunctionBase Class以创建你的自定义缓动函数。


    Sheldon _Xiao[MSFT]
    MSDN Community Support | Feedback to us
    Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2012年4月17日 3:54
    版主
  • 4.5. 为什么在使用 BitmapEffect 类时,Visual Studio会给出一个编译警告?

    BitmapEffects是不推荐使用的。

    虽然BitmapEffects类以及它的派生类还可以被找到,但是它们已经被禁用。在下列条件被满足的情况下,对应的效果将会通过硬件加速渲染管道被渲染:

    如果上述条件不被满足,BlurBitmapEffect将不会有任何效果。

    同时,当遇到BitmapEffect或者它的派生类时,Visual Studio将会报出一个编译警告。

    DrawingContext.PushEffect方法已经被弃用。

    建议的规避方法:请不要继续使用旧的BitmapEffect类及其派生类。相应的请使用派生自Effect类的新类:BlurEffect,DropShadowEffect,和ShaderEffect.

    你也可以通过派生自ShaderEffect来创建自己的效果。


    Sheldon _Xiao[MSFT]
    MSDN Community Support | Feedback to us
    Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2012年4月17日 3:55
    版主
  • 5.1. 如何使用 TextFormattingMode, TextRenderingMode以及 TextHintingMode属性?

    WPF 4拥有一个新的文本呈现堆栈。TextOptions类提供了这三个附加属性来使你控制元素中文本显示的方式。
    WPF text team的这篇博客WPF 4.0 Text Stack Improvements详细解释了这三个附加属性的用法。


    Sheldon _Xiao[MSFT]
    MSDN Community Support | Feedback to us
    Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2012年4月17日 3:55
    版主
  • 5.2. 如何改变光标选择区域和光标样式?

    WPF 4之前,我们只能通过规避方法来达到这种效果。在WPF 4中,我们可以为输入和阅读控件指定描画光标选择区域和光标的画刷,比如TextBoxRichTextBox以及FlowDocumentReader。这是通过TextBoxBase类的SelectionBrush属性和CaretBrush属性来完成的。


    Sheldon _Xiao[MSFT]
    MSDN Community Support | Feedback to us
    Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2012年4月17日 3:56
    版主
  • 6.1. 什么是动态对象以及如何在 WPF 4 中绑定一个动态对象?

    动态对象在运行时而不是在编译时向外暴露成员属性和成员方法。这个特性使你可以创建对象去与一些静态类型或者格式不匹配的结构体进行交互。

    WPF 4支持动态对象作为绑定源。你可以绑定有效的属性以及实现IDynamicMetaObjectProvider接口的对象索引(DynamicObject实现了IDynamicMetaObjectProvider接口)。

    请参考如下表格以了解动态对象数据绑定的权限要求信息:
    http://msdn.microsoft.com/zh-cn/library/ms743643.aspx#permissions


    Sheldon _Xiao[MSFT]
    MSDN Community Support | Feedback to us
    Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.


    2012年4月17日 3:56
    版主
  • 6.2. KeyBinding 或者 MouseBinding WPF 4 有哪些改变?

    WPF 4中,InputBinding继承自Freezable而不是DependencyObject现在当一个类级别的InputBinding在它被注册后将被冻结而不是继续可以被改变。


    Sheldon _Xiao[MSFT]
    MSDN Community Support | Feedback to us
    Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2012年4月17日 3:58
    版主
  • 7.1. 如何在 WPF 浏览器应用程序 XBAP 中访问页面的 HTML DOM 对象?

    在一个XBAP程序承载于HTML框架中时,你可以通过BrowserInteropHelper.HostScript属性获取HTML窗体对象,自定义脚本函数以及全局变量。

    请参考WPF XAML Browser Applications Overview - Communicating with the Host Web Page以获得更多细节信息。

    或者参考Lester Lobo的博客Script Interop in Xbap以获取更多样例代码。


    Sheldon _Xiao[MSFT]
    MSDN Community Support | Feedback to us
    Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2012年4月17日 3:58
    版主
  • 8.1. 如何在 WPF 中使用 Windows 7 操作系统任务栏的新特性?

    System.Windows.Shell 命名空间包含了一些类使你可以使用Windows 7任务栏新特性。例如,设置任务栏覆盖图标,自定义跳转列表,自定义任务栏缩略图以及缩略图按钮等等。

    Pete BrownWindowsClient.NET上的“How Do I”视频向我们展示了使用任务栏新特性的基础知识。

    How Do I: Implement Windows 7 Taskbar Icon Overlays with WPF 4
    How do I: Use Windows 7 Taskbar Progress Reporting from WPF 4


    Sheldon _Xiao[MSFT]
    MSDN Community Support | Feedback to us
    Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2012年4月17日 3:59
    版主
  • 9.1. WPF Silverlight 的设计器有什么新特性以及如何安装设置?

    Visual Studio 2010中做出了许多设计器的改进以帮助开发者创建WPF以及Silverlight程序。

    Karl Shifflett的博客Setting Up Visual Studio for WPF and Silverlight Development详细解释了设计器环境的安装,并且介绍了设计器每个元素的相关功能。


    Sheldon _Xiao[MSFT]
    MSDN Community Support | Feedback to us
    Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2012年4月17日 3:59
    版主