`
clingingboy
  • 浏览: 26952 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
最近访客 更多访客>>
社区版块
存档分类
最新评论

wpf开发常见问题(1)

阅读更多

      经过一段时间wpf的学习和实际开发.现在与大家分享下,在实际中wpf遇到的一些实际问题.silverlight 2.0正式版已经出来.sliverlight的功能应该与wpf大步分类似。其中的经验照样可以套用到sliverlight上.现在开始.

 

一.与模板相关问题

1.如何取得模板中的元素?

直切重点

(1)第一步确定控件相关ContentPresenter.给出一个扩展方法

public static childItem FindVisualChild<childItem>(this DependencyObject obj)
where childItem : DependencyObject
{
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
    {
        DependencyObject child = VisualTreeHelper.GetChild(obj, i);
        
        if (child != null && child is childItem)
            return (childItem)child;
        else
        {
            childItem childOfChild = FindVisualChild<childItem>(child);
            if (childOfChild != null)
                return childOfChild;
        }
    }
    return null;
}
(2)通过ContentControl控件的ContentTemplate属性的FindName方法获取元素
public static object FindTemplateChild(this ContentControl obj, string name)
{
    ContentPresenter content = obj.FindVisualChild<ContentPresenter>();
    object child = obj.ContentTemplate.FindName(name, content);
    return child;
}
进一步用泛型封装
public static childItem FindTemplateChild<childItem>(this ContentControl obj, string name)
    where childItem : DependencyObject
{

    ContentPresenter content = obj.FindVisualChild<ContentPresenter>();
    object child = obj.ContentTemplate.FindName(name, content);
    if (child != null && child is childItem)
    return (childItem)child;

    return null;
}
在实际情况中,我们还可能用到winfroms控件,所以再来一个
public static childItem FindFormsTemplateChild<childItem>(this ContentControl obj, string name, FrameworkElement parent)
    where childItem : System.Windows.Forms.Control
{
    object child = obj.ContentTemplate.FindName(name, parent);
    if (child != null && child is childItem)
        return (childItem)child;
   
    return null;
}

2.如果获取元素父级元素?

public static childItem FindAncestor<childItem>(this Visual visual)
    where childItem : Visual
{
    while (visual != null && !typeof(childItem).IsInstanceOfType(visual))
    {
        visual = (Visual)VisualTreeHelper.GetParent(visual);
        
    }
    if (visual != null && visual is childItem)
        return (childItem)visual;

    return null;
}

3.何时可以取到模板的元素?

在你需要取模板元素的时候,必须保证模板已经加载了.那如何才能保证模板已经加载?

3-1确保控件(元素)在页面上出现.这个讲法比较通俗,意思就是要保证模板已经加载完成.给出一个简单的例子(目的,用Tab1的button事件去取得Tab2的ListBox控件的模板)

<Grid>
    <Grid.Resources>
        <DataTemplate x:Key="demo">
            <Label x:Name="labelCrl" Background="Red" Content="{Binding}"></Label>
        </DataTemplate>
    </Grid.Resources>
    <TabControl>
        <TabItem Header="Button">
            <Button Height="23" Margin="143,0,82,81" Name="button1" VerticalAlignment="Bottom" Click="button1_Click">Button</Button>
        </TabItem>
        <TabItem Header="ListBox">
            <StackPanel>
                <ListBox x:Name="boxDemo" ItemTemplate="{StaticResource demo}"></ListBox>
                <ListBox Margin="10,0,0,5" Name="lb">
                    <ListBoxItem>Item 0</ListBoxItem>
                </ListBox>
            </StackPanel>
           
        </TabItem>
    </TabControl>
</Grid>

后端,以下代码是无效,除非第一次进来已经切换过Tab2,模板加载完成后才有效.

private void button1_Click(object sender, RoutedEventArgs e)
{
    //if in different tabitem,I can't fetch the ListBoxItem
    ListBoxItem obj = boxDemo.ItemContainerGenerator.ContainerFromIndex(0) as ListBoxItem;
    ContentPresenter obj2 = boxDemo.FindVisualChild<ContentPresenter>();
    Object label = obj.ContentTemplate.FindName("labelCrl", obj2);
}

那如何解决这个问题?

(1)利用数据绑定的功能,只更改相关属性,模板则自动更新

(2)不要在button事件中更改ui,定义出你需要更改的属性,然后在控件的Onload事件中更改.如你需要更改Label的BackGround,你可以定义一个属性,然后把上面这段代码提取到ListBox的Onload事件当中.

3-2 利用Dispatcher属性异步等待模板加载完成

在实际开发中,有可能会遇到这种现象,取模板的元素,有时成功有时失败,不同机器配置取模板的速度都会不同. 在未理解Dispatcher的使用之前,为防止模板未加载完成.我利用System.Timers.Timer 来等待模板加载完成.

如下示例,使用一个Timer对象反选一个列表中模板中的元素,如果没有取到对象的话,则重新执行Timer事件(Start方法).因为不在同一线程,所以还是需要调用Dispatcher的BeginInvoke方法,进行异步操作.

private Timer timer;
       
public ItemListView()
{
    timer = new Timer();
    timer.Interval = 100;
    timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
}

void timer_Elapsed(object sender, ElapsedEventArgs e)
{
    timer.Stop();
    Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
        new Action(this.UnCheckAll));
}

public void UnCheckAll()
{

    if (this.SelectedItem != null)
    {
        foreach (var item in this.ItemsSource)
        {
            DependencyObject viewItem = this.ItemContainerGenerator.ContainerFromItem(item);
            if (item != this.SelectedItem)
            {

                if (viewItem != null)
                {
                    CheckBox box = viewItem.FindVisualChild<CheckBox>();
                    if (box != null)
                    {
                        box.IsChecked = false;
                    }
                    else
                    {
                        timer.Start();
                    }
                }
            }
        }
    }
}

以上的做法虽然可以解决问题,但并非最好办法.勉强可用.

设置异步请求的优先级别即DispatcherPriority.看一下以下的说明,默认一般都设置为Normal,我们可以设置为Background,这样就万无一失了

Capture

 

现在以上的代码变为

public ItemListView()
{
   this.Loaded+=new RoutedEventHandler(ItemListView_Loaded);
}

void ItemListView_Loaded(object sender, RoutedEventArgs e)
{
    Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Background,
         new Action(this.UnCheckAll));
}

这一点很重要,取模板之前最好用Dispatcher的BeginInvoke方法去取模板元素,这样不会出错.

4.如何在后端定义一个默认模板?

在定义模板选择器的时候,如果用户未自定义模板的话,可以简单的在后端定义一个模板,方法如下,此方法并不推荐使用了.

private DataTemplate CreateDefault()
{
    DataTemplate tpl = new DataTemplate();
    FrameworkElementFactory box = new FrameworkElementFactory(typeof(CheckBox));
    Binding bind = new Binding();
    box.SetBinding(CheckBox.TagProperty, bind);
    box.AddHandler(CheckBox.ClickEvent, new RoutedEventHandler(selectChanged));
    tpl.VisualTree = box;
    return tpl;
}

其他方面就看msdn和相关书籍吧,以上方法已经很实用,能解决大部分问题了.

 

二.数据绑定相关

1.赋值不等于绑定

this.DataContext = this.ViewModel;

一般情况下,一个DataContext是通过赋值来执行的.与其绑定的数据来源均实现INotifyPropertyChanged,以实现双向绑定通知

然后在其DataContext 范围内的元素均能共享这个数据源,进行绑定

this.announceContent.SetBinding(AnnounceDetailView.BackgroundProperty, new Binding("xxx"));

这个时候再进行属性的更改,绑定的属性将会改变.

this.announceContent.Background = Brushes.Red;

当进行主从绑定的时候,很容易看到DataContext属性就毫不犹豫的进行赋值操作,这时应该进行绑定操作,不要做了赋值的操作,还在为自己狡辩,我真的绑定了怎么没出效果:)

2.只有依赖属性才可以绑定

数据绑定的类型转换器非常的常用,动不动就需要,有时候你需要传入一个参数,而且是依赖属性。可以参考我这里以前写的一篇

http://www.clingingboy.cn/index.php/archives/36

3.如何用绑定语法绑定整个对象

如果要绑定初始对象,可以这样写.加Path=.跟不加有区别的哦

{Binding Path=.}

4.绑定到字典

顺便把以前写的拿过来

{Binding dd[xxx]}

5.绑定选择对象

(1)先设置SelectedValuePath

(2)绑定SelectedItem

(3)绑定SelectedValue

如果在xmal中以上属性设置无效,需要在后端设置,因为无法判断先设置哪个属性即Selector控件需要选择一个默认的对象.

否则的话可以尝试绑定后更改绑定的对象.

6.绑定的内存泄露问题

看这个http://support.microsoft.com/kb/938416

7.与绑定相关的验证问题

我认为wpf内置的验证还不够方面,在.net 3.5sp1对验证功能进行了一些改善.

这个问题将单独拿出来讨论,我将在这篇随笔里面进行补充,提供给大家一种解决方案,供大家参考。

http://www.cnblogs.com/Clingingboy/archive/2008/08/24/1274934.html

8.绑定数据,但要注意性能.

为了实现绑定,有时会从数据库里面把绑定的数据一次性全部取出来,这样没必要,绑定很好,但也要注意性能.

另外其他的相关数据绑定的可以看msdn,很详细,关键还是多练.

三.资源文件相关

1.编译后的资源文件加载速度更快.

默认wpf提供了多种皮肤,而其是以dll的方式提供了,如PresentationFramework.Luna,一个xp下默认的皮肤.在开发过程中(vista)为了统一界面风格,我们需要加载xp皮肤.

Uri url = new Uri("PresentationFramework.Luna;V3.0.0.0;31bf3856ad364e35;component/themes/luna.normalcolor.xaml", UriKind.Relative);
System.Windows.ResourceDictionary resource = (System.Windows.ResourceDictionary)System.Windows.Application.LoadComponent(url);
System.Windows.Application.Current.Resources.MergedDictionaries.Add(resource);

同样当我们在开发后期我们应该把我们的资源文件整理到一个项目里面进行编译后进行加载,这样性能优于把资源放在每个相关的xaml中.wpf版本的雅虎通就是这么做的:).

这篇文章可以进行比较.很明显的,推荐看一下.

http://www.codeproject.com/KB/WPF/wpfskins.aspx

2.给资源合理分类

当然是为了更好的管理资源文件了,可以参考下此文.

http://www.paulstovell.com/blog/xaml-and-wpf-coding-guidelines

还同时给出了如何更好的写xaml的方案.

先写到这里,有时间再写第二篇,给大家一个参考

public ReferencedAssemblySkin(string name, Uri resourceUri) : base(name)
{
    this._resourceUri = resourceUri;
}
分享到:
评论

相关推荐

    避开10大常见坑:DeepSeekAPI集成中的错误处理与调试指南.pdf

    在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!

    前端分析-2023071100789

    前端分析-2023071100789

    基于kinect的3D人体建模C++完整代码.cpp

    基于kinect的3D人体建模C++完整代码.cpp

    搞机工具箱10.1.0.7z

    搞机工具箱10.1.0.7z

    GRU+informer时间序列预测(Python完整源码和数据)

    GRU+informer时间序列预测(Python完整源码和数据),python代码,pytorch架构,适合各种时间序列直接预测。 适合小白,注释清楚,都能看懂。功能如下: 代码基于数据集划分为训练集测试集。 1.多变量输入,单变量输出/可改多输出 2.多时间步预测,单时间步预测 3.评价指标:R方 RMSE MAE MAPE,对比图 4.数据从excel/csv文件中读取,直接替换即可。 5.结果保存到文本中,可以后续处理。 代码带数据,注释清晰,直接一键运行即可,适合新手小白。

    性价比革命:DeepSeekAPI成本仅为GPT-4的3%的技术揭秘.pdf

    在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!

    基于ANSYS LSDyna的DEM-SPH-FEM耦合模拟滑坡入水动态行为研究,基于ANSYS LSDyna的DEM-SPH-FEM耦合的滑坡入水模拟分析研究,基于ansys lsdyna的滑坡入水

    基于ANSYS LSDyna的DEM-SPH-FEM耦合模拟滑坡入水动态行为研究,基于ANSYS LSDyna的DEM-SPH-FEM耦合的滑坡入水模拟分析研究,基于ansys lsdyna的滑坡入水模拟dem-sph-fem耦合 ,基于ANSYS LSDyna; 滑坡入水模拟; DEM-SPH-FEM 耦合,基于DEM-SPH-FEM耦合的ANSYS LSDyna滑坡入水模拟

    auto_gptq-0.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

    auto_gptq-0.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

    复件 复件 建设工程可行性研究合同[示范文本].doc

    复件 复件 建设工程可行性研究合同[示范文本].doc

    13考试真题最近的t64.txt

    13考试真题最近的t64.txt

    Microsoft Visual C++ 2005 SP1 Redistributable PackageX86

    好用我已经解决报错问题

    嵌入式开发入门:用C语言点亮LED灯的全栈开发指南.pdf

    # 踏入C语言的奇妙编程世界 在编程的广阔宇宙中,C语言宛如一颗璀璨恒星,以其独特魅力与强大功能,始终占据着不可替代的地位。无论你是编程小白,还是有一定基础想进一步提升的开发者,C语言都值得深入探索。 C语言的高效性与可移植性令人瞩目。它能直接操控硬件,执行速度快,是系统软件、嵌入式开发的首选。同时,代码可在不同操作系统和硬件平台间轻松移植,极大节省开发成本。 学习C语言,能让你深入理解计算机底层原理,培养逻辑思维和问题解决能力。掌握C语言后,再学习其他编程语言也会事半功倍。 现在,让我们一起开启C语言学习之旅。这里有丰富教程、实用案例、详细代码解析,助你逐步掌握C语言核心知识和编程技巧。别再犹豫,加入我们,在C语言的海洋中尽情遨游,挖掘无限可能,为未来的编程之路打下坚实基础!

    auto_gptq-0.4.2-cp38-cp38-win_amd64.whl

    auto_gptq-0.4.2-cp38-cp38-win_amd64.whl

    自动立体库设计方案.pptx

    自动立体库设计方案.pptx

    手把手教你用C语言实现贪吃蛇游戏:从算法设计到图形渲染.pdf

    # 踏入C语言的奇妙编程世界 在编程的广阔宇宙中,C语言宛如一颗璀璨恒星,以其独特魅力与强大功能,始终占据着不可替代的地位。无论你是编程小白,还是有一定基础想进一步提升的开发者,C语言都值得深入探索。 C语言的高效性与可移植性令人瞩目。它能直接操控硬件,执行速度快,是系统软件、嵌入式开发的首选。同时,代码可在不同操作系统和硬件平台间轻松移植,极大节省开发成本。 学习C语言,能让你深入理解计算机底层原理,培养逻辑思维和问题解决能力。掌握C语言后,再学习其他编程语言也会事半功倍。 现在,让我们一起开启C语言学习之旅。这里有丰富教程、实用案例、详细代码解析,助你逐步掌握C语言核心知识和编程技巧。别再犹豫,加入我们,在C语言的海洋中尽情遨游,挖掘无限可能,为未来的编程之路打下坚实基础!

    性能对决:DeepSeek-V3与ChatGPTAPI在数学推理场景的基准测试.pdf

    在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!

    从零到一:手把手教你用Python调用DeepSeekAPI的完整指南.pdf

    在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!

    为什么你的switch总出bug?90%新手不知道的break语句隐藏规则.pdf

    # 踏入C语言的奇妙编程世界 在编程的广阔宇宙中,C语言宛如一颗璀璨恒星,以其独特魅力与强大功能,始终占据着不可替代的地位。无论你是编程小白,还是有一定基础想进一步提升的开发者,C语言都值得深入探索。 C语言的高效性与可移植性令人瞩目。它能直接操控硬件,执行速度快,是系统软件、嵌入式开发的首选。同时,代码可在不同操作系统和硬件平台间轻松移植,极大节省开发成本。 学习C语言,能让你深入理解计算机底层原理,培养逻辑思维和问题解决能力。掌握C语言后,再学习其他编程语言也会事半功倍。 现在,让我们一起开启C语言学习之旅。这里有丰富教程、实用案例、详细代码解析,助你逐步掌握C语言核心知识和编程技巧。别再犹豫,加入我们,在C语言的海洋中尽情遨游,挖掘无限可能,为未来的编程之路打下坚实基础!

    用deepseek变现实操流程

    用deepseek变现实操流程,小白必看。

    10个必知的DeepSeekAPI调用技巧:从鉴权到限流全解析.pdf

    在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!

Global site tag (gtag.js) - Google Analytics