Skip to content

JohnYang1210/WPFTestDemo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

44 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

在Git命令窗口,执行解除SSL验证命令脚本完成设置操作。

git config --global http.sslVerify "false"

本仓库仅用作wpf的各种方面的测试,学习。

This repository is only for the purpose of small demos of test or study of WPF.

  • 逻辑树可以扩展为细节更丰富的可视化树,but how? how this works? and why we need to learn about this?

原因在于,每个控件都有一个内置的方法,用于确定如何渲染控件(作为一组 更基础的元素),该方法称为控制模板(control template),是用 xaml标记块定义的

需要学习的原因是,虽然可以通过样式来改变可视化中的元素,改变控件的外观, 但有些特定的细节很难,甚至无法修改,因此,可以诉诸于可视化树,来解决这个问题, 此外,可为控件创建新模板,对于这种情况,控件模板将用于按期望的方式构件 可视化树。

  • DataTemplate和ControlTemplate的区别: DataTemplate是用以控制展现数据的方式,是与数据相关的,所以是ItemTemplate的 值,而DataTemplate中用binding来绑定从ItemSource传来的数据。 ControlTemplate是单纯用来改变控件外形的,与数据无关,比如 Button.Template的值就是ControlTemplate类型,是构建可视化树的工具。 也就是说ItemControl打破了,里面是DataTemplate来定义如何展现数据的 而ControlTemplate就是普通的控件,打破了,往里面看,更微小的构造

  • Margin控制的是控件与控件的距离,Padding控制的是内部文字与控件外边缘的距离。

  • 在DataTemplate中的控件可以通过Tag属性,将Binding传入,作为 后续选中的哪一项的标识,如果是{Binding},那么就是把Item整体传入。

  • 从项容器获取数据,动态改变模板<详:DataTemplateDataTriggerDemo.xaml>

<DataTemplate x:Key="listBoxItemTemplate">
            <Border Margin="5" BorderThickness="1" BorderBrush="SteelBlue" 
                    CornerRadius="4">
                <StackPanel Margin="3">
                    <TextBlock Text="{Binding Name}"/>
                    <StackPanel>
                        <StackPanel.Style>
                            <Style>
                                <Style.Triggers>
                                    <DataTrigger 
                                        Binding="{Binding Path=IsSelected, RelativeSource={
                                        RelativeSource 
                                        Mode=FindAncestor,
                                        AncestorType={x:Type ListBoxItem}
                                        }}" Value="false">
                                        <Setter Property="StackPanel.Visibility" Value="Collapsed"/>
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </StackPanel.Style>
                        <TextBlock Margin="3" Text="{Binding Description}"
                                  TextWrapping="Wrap" MaxWidth="250" HorizontalAlignment="Left"/>
                        <Image Source="{Binding ImagePath}"/>
                    </StackPanel>
                </StackPanel>
            </Border>
        </DataTemplate>
  • 视图 当创建一个绑定,WPF会创建一个叫做视图的对象,代表对象的集合,并且呈现那个集合到目标 控件。一个视图是一个CollectionView类的对象,并且管理数据的逻辑表示。可以执行如下功能: (1) 保存集合中“当前”项的记录 (2)进行过滤---根据一些准则来逻辑化的排除一些数据成员[CollectionView的Filter属性,其中Filter是Func<bool,object>] (3)根据指定的属性的值来排列数据对象[CollectionView的SortDescriptions,其中添加的是SortDescription对象] (4)划分数据对象到不同的组

  • ControlTemplate WPF中,控件的外在模样和其功能是解耦的,外在模样可以通过ControlTemplate 来重新定义,如果还想通过Content来传递显示文字信息,就需要在ControlTemplate 中添加<ContentPresenter/>来定位,即ContentPresenter仅仅是一个占位符, 但值得注意的还有两点:(1)若要使用ContentPresenter,就必须为ControlTemplate设定 TargetType属性。(2)ControlPresenter若要使用其外在ControlTemplate的某些属性的值 可以通过TemplateBinding

  • 如果编译器看到一个程序的startupUri是一个Page,它就创建一个NavigationWindow来控制它,

  • 这就是为什么在PageDemo中看,没有去指定导航宿主。

  • 命令 实际应用程序中,如果要通过不同的动作和用户界面元素来执行一些相同的任务,最简单的虽然是将用户界面触发的事件都 绑定到一个执行该任务的方法,但当考虑该任务反向对用户界面的状态有影响时,问题就变得复杂了,如果没有正确 处理好用户界面状态,就可能会使不同状态的代码块不正确的相互重叠,从而导致某个控件在不应该可用的时候而 被启用。 幸运的是,命令可以解决这个问题,将相同的命令连接到不同控件,从而不需要重复编写事件处理代码,更重要的是 ,当连接的命令不可用时,命令特性通过自动禁用控件来管理用户界面状态;当然,WPF命令仍然有一些重要的问题没有解决, (1)命令跟踪(例如,保留最近命令的历史)(2)“可撤销的”命令(3)具有状态并可处于不同“模式”的命令(例如, 可被打开或关闭的命令)

命令为什么需要路由事件: 命令不应该由命令对象负责执行命令么?如果直接使用ICommand接口创建自己的命令,确实如此。代码应当被硬连接到命令, 从而可以通过相同的方式工作,而不管是什么操作触发了命令,这时,不需要事件冒泡。 然而,WPF使用了大量预先构建的命令,这些命令没有包含任何实际的代码,它们只是为了方便地定义代表常见应用程序 任务。**为了使用这些命令,需要使用命令绑定,为代码引发事件,为确保可在某个位置处理事件,甚至事件是由同一个窗口 的不同命令源引发的,所以需要使用事件冒泡的功能。 那么问题又来了,为什么非要使用预先构建的命令?因为它们为集成提供了更好的可能。例如,第三方开发人员可创建使用预先构建 的Print命令,只要应用程序使用相同预先构建的命令,在应用程序中关联打印时,就不需要做任何额外工作了。

命令架构图:

触发命令库中的命令的最简单的方法是将它们关联到已实现了ICommandSource接口的控件,其中包括继承自ButtonBase类的控件 (Button,CheckBox(均为单击发送命令)),单独的ListBoxItem(双击时发送命令),HyperLink(单击发送命令),以及MenuItem(单击发送命令)。

CommandBinding的CanExecute,Executed中的sender是CommandBinding被添加到的CommandBindings所在的控件。 如:

<TextBox.CommandBindings>
    <CommandBinding Command=...
    />
</TextBox.CommandBindings>

那么上述的CommandBinding的Executed,CanExecute中的sender就是该TextBox。

  • ListBox由于条目比较多,自动出现了scrollViewer时候,滚动中键,
  • 实现ListBox滚动的方法,详CommandDemoC.xaml方法一:
private void initBindMouseWheel()
       {
           PreviewMouseWheel += (sender, e) =>
           {
               var eventArg = new MouseWheelEventArgs(e.MouseDevice, 1, e.Delta);
               eventArg.RoutedEvent = UIElement.MouseWheelEvent;
               eventArg.Source = sender;
               this.lstHistory.RaiseEvent(eventArg);
           };
       }

```
`方法二`:
外层包裹ScrollViewer
```xaml
<ScrollViewer Grid.Row="3" BorderBrush="Black" BorderThickness="1" Margin="5" x:Name="scrollViewer" MouseWheel="scrollViewer_MouseWheel">
           <ListBox Grid.Row="3" Name="lstHistory" Margin="5" DisplayMemberPath="CommandName" >
           </ListBox>
       </ScrollViewer>

```

```c#
MainWindow.cs:
窗体构造函数中:
this.lstHistory.AddHandler(PreviewMouseWheelEvent, new MouseWheelEventHandler(lstHistory_MouseWheel));
或:
this.AddHandler(PreviewMouseWheelEvent, new MouseWheelEventHandler(lstHistory_MouseWheel));


private void lstHistory_MouseWheel(object sender, MouseWheelEventArgs e)
       {
           if (e.Delta > 0)
           {
               scrollViewer.LineUp();
           }
           else
           {
               scrollViewer.LineDown();
           }
       }

```

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages