什么是WPF最糟糕的陷阱?

时间:2011-02-10 13:26:15

标签: wpf

我已经开始把自己列为“WPF陷阱”的列表:那些让我烦恼的事情,我不得不写下来记住,因为我每次都为他们摔倒......

现在,我很确定你们曾经偶然发现类似情况,我希望你们分享一下你们在这个问题上的经验:

有什么时间可以帮到你?你觉得最烦人的那个?

(我有一些似乎没有解释的问题,也许你的提交将解释它们)

以下是我的一些“个人”陷阱(随机呈现):

  1. 即使单击位于控件(例如标签)的“透明”背景上而不仅仅是内容(本例中为文本)上,也会触发MouseEvent,控件的背景必须设置为“Brushes.Transparent”而不仅仅是“null”(标签的默认值)

  2. WPF DataGridCell的DataContext是单元所属的RowView,而不是CellView

  3. 当在ScrollViewer中时,滚动条本身由滚动查看器管理(即设置属性,例如ScrollBar.Value无效)

  4. 按“F10”时,
  5. Key.F10不会被触发,而是Key.System,你必须找e.SystemKey才能获得Key.F10 < / p>

  6. ......现在你已经开始了。

10 个答案:

答案 0 :(得分:13)

  1. 始终观看输出窗口 绑定错误。忽略输出 窗口是流泪的食谱。

  2. 在调试绑定失败时,在绑定中使用PresentationTraceOptions.TraceLevel =“High”来获取详细的绑定信息。

  3. 创建静态的,不变的资源,例如画笔PresentationOptions:Freeze =“True”以在运行时节省资源。

  4. 使用WPF DataGrid作为数据网格。将其修改为像Excel这样的行为是一个巨大的痛苦。

  5. BindingList<T>与CollectionViewSource不兼容。改为从您的视图模型中公开ObservableCollection<T>

  6. 互联网提供了六种不同的想法,用于在WPF文本框中显示CueBanner文本。他们都破了。

答案 1 :(得分:7)

1)当我从WinForms转换时,过去常常每半小时给我一次:在UI上放置随机文本时使用TextBlock instead of Label(或者根本不使用任何标签,如果文字是静态的!)

2)DataTriggers / Triggers不能放入Control.Triggers,但必须进入Control.Styles / Style / Style.Triggers

3)如果XAML将属性识别为集合属性,则属性的类型必须实现IList,而不是IList<T>

4)绑定捕获异常。

5)使用单例转换器/静态转换器类,因此每次使用时都不必创建新的转换器。

6)必须明确指定DependencyProperty默认值的类型:0u为uint,(float) 0为float,0.0为double ...

7)It matters if the control's property definitions are before or after its content

8)永远不要使用PropertyMetadata来设置引用类型DependencyProperty的默认值。同一个对象引用将分配给拥有类的所有实例。

答案 2 :(得分:3)

第一次出发时,会得到我的主要问题是

  • 列出因遗忘而未更新的内容 使用ObservableCollection
  • 属性未更新 忘了添加OnPropertyChanged 或错误地键入属性 名称

最近我偶然发现了这些问题

答案 3 :(得分:2)

ToolTips和ContextMenus不共享其所有者的DataContext?我认为这首先得到了每个人

答案 4 :(得分:2)

  • 如果启用,Button.IsCancel会将false分配给Window.DialogResult,但会Button.IsDefault否。
    它们是如此相似,对我来说,起初看起来很直观,两者都应该关闭对话。我通常打破MVVM并在代码隐藏

  • 中解决这个问题
  • Button.IsCancel + Command =对话框无法关闭(Window.DialogResult未分配)但Command执行了 据我了解:如果IsCancel的优先级高于Command,那么在 Esc 上,它会指定“假”&#39;到DialogResultCommand不会被调用。或者,如果Command具有更高的优先级,则首先调用它,然后分配DialogResult。我不明白它是如何跳过的?

  • 绑定吞下异常!
    从OOP的角度来看,它不仅会在调试时节省时间,因为如果抛出异常,则意味着我们系统中的某些地方发生了异常情况(从错误的数据供应到未经授权访问内存故障),所以它可以是只有在你知道该怎么做才能处理。你不能catch(Exception){}抓住所有人,然后忽略。如果程序中存在未知异常,则应通知用户,记录并关闭,不要假装一切正常......

  • HeaderContent只能有一个子控件且没有填充
    一切都应该有填充甚至逻辑控件(容器),对吧?我认为这是不一致的。您怎么看?

  • 如果您通过ListBox将焦点设置为FocusManager.FocusedElement,您仍然无法通过键盘切换内容,因为焦点设置为{{1} es es不是它的内容。我想我不知道其他UI API会向UI程序员公开类似控件框架的东西它应该从我们这里封装,因为抽象的ListBox代表一个列表,它只是一个列表,而不是一个盒子里的东西列表。 好吧它的名字中有盒子但仍然...... 我们这里几乎有两个不同的控件。 MVVM not breaking fix

  • 默认情况下,
  • ListBoxListBox.IsSynchronizedWithCurrentItem,因此如果您为false指定了不同的值或null,那么ItesSource仍会保留旧值,直到用户选择来自新名单的东西。例如,它可能会弄乱SelectedItem。需要每次手动设置。

  • CanExecute中没有暴露绑定会导致时间浪费和肮脏的黑客攻击......但它仍有一个字符串属性PasswordBox暴露,所以甚至不要试图争论安全性因为Snoop ......

  • 这不是问题,但是表格布局是如此IE6 IMO。容器设计有助于将内容与其布局分开 因为每次我需要在某些地方更改某些内容时,我都需要使用PasswordBox.PasswordGrid.Row。是的,我们有Grid.ColumnDockPanel和其他人,但您无法在其中进行一些列对齐。 (而且StackPanel就像完全独立的问题一样)如果DockPanel可以更加自定义,那么我认为这是理想的。你总是需要在网格和面板之间进行选择,通常如果你获得了一些东西,你就会失去其他东西。

答案 5 :(得分:1)

上周我非常精彩:

模板化RichTextBox时,模板内部的事件处理遵循一条奇怪的路线,既没有隧道也没有冒泡

例如:对于应该隧道的事件:事件首先通过ContentPresenter隧道,然后从模板顶部隧道返回。

请参阅my question on the subject

答案 6 :(得分:1)

在WPF中没有干净的方法来处理验证,我不是IDataErrorInfo默认提供的魔术字符串的粉丝:

  public string this[string columnName]
  {
        if (columnName == "FirstName")
        {
            if (string.IsNullOrEmpty(FirstName))
                result = "Please enter a First Name";
        }
  }

但是,我尝试过很多框架,比如SimpleMVVM,FluentValidation和MVVMValidation,BY FAR MVVM Validation是最好的做法:

Validator.AddRule(() => RangeStart,
              () => RangeEnd,
              () => RuleResult.Assert(RangeEnd > RangeStart, "RangeEnd must be grater than RangeStart");

答案 7 :(得分:0)

我个人最喜欢的是这个:

public double MyVariable
{
    get { return (double)GetValue(MyVariableProperty); }
    set { SetValue(MyVariableProperty, value); }
}
public static readonly DependencyProperty MyVariableProperty = DependencyProperty.Register(
    "MyVariable", typeof(double), typeof(MyControl), new UIPropertyMetadata(0));

尝试一下,一旦声明了这个属性就会崩溃。为什么?因为0显然不能使用反射分配给double。

不是真的有问题,而是建议:使用Snoop或类似的东西,如果你不使用它,你一定是疯了......疯了我告诉你!

答案 8 :(得分:0)

Binding.StringFormat仅在目标属性的类型为string时才有效。

答案 9 :(得分:0)

  • TreeView的{​​{1}}属性不可设置。相反,您必须将SelectedItem的{​​{1}}属性绑定到项目的视图模型,然后在其中设置选择。

  • 另一方面,
  • TreeViewItem的SelectedItem是可设置的,但 是可设置的,但是项目选择不等于项目焦点。如果要实现正确的键盘导航以及从viewmodel中选择项目,则必须实现手动焦点修复,例如:

    IsSelected

    ...并在每次从viewmodel更改所选项目时调用它:

    ListBox