我已经开始把自己列为“WPF陷阱”的列表:那些让我烦恼的事情,我不得不写下来记住,因为我每次都为他们摔倒......
现在,我很确定你们曾经偶然发现类似情况,我希望你们分享一下你们在这个问题上的经验:
有什么时间可以帮到你?你觉得最烦人的那个?
(我有一些似乎没有解释的问题,也许你的提交将解释它们)
以下是我的一些“个人”陷阱(随机呈现):
即使单击位于控件(例如标签)的“透明”背景上而不仅仅是内容(本例中为文本)上,也会触发MouseEvent,控件的背景必须设置为“Brushes.Transparent”而不仅仅是“null”(标签的默认值)
WPF DataGridCell的DataContext是单元所属的RowView,而不是CellView
当在ScrollViewer中时,滚动条本身由滚动查看器管理(即设置属性,例如ScrollBar.Value无效)
Key.F10
不会被触发,而是Key.System
,你必须找e.SystemKey
才能获得Key.F10
< / p>
......现在你已经开始了。
答案 0 :(得分:13)
始终观看输出窗口 绑定错误。忽略输出 窗口是流泪的食谱。
在调试绑定失败时,在绑定中使用PresentationTraceOptions.TraceLevel =“High”来获取详细的绑定信息。
创建静态的,不变的资源,例如画笔PresentationOptions:Freeze =“True”以在运行时节省资源。
使用WPF DataGrid作为数据网格。将其修改为像Excel这样的行为是一个巨大的痛苦。
BindingList<T>
与CollectionViewSource不兼容。改为从您的视图模型中公开ObservableCollection<T>
。
互联网提供了六种不同的想法,用于在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)
第一次出发时,会得到我的主要问题是
最近我偶然发现了这些问题
答案 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;到DialogResult
和Command
不会被调用。或者,如果Command
具有更高的优先级,则首先调用它,然后分配DialogResult
。我不明白它是如何跳过的?
绑定吞下异常!
从OOP的角度来看,它不仅会在调试时节省时间,因为如果抛出异常,则意味着我们系统中的某些地方发生了异常情况(从错误的数据供应到未经授权访问内存故障),所以它可以是只有在你知道该怎么做才能处理。你不能catch(Exception){}
抓住所有人,然后忽略。如果程序中存在未知异常,则应通知用户,记录并关闭,不要假装一切正常......
HeaderContent
只能有一个子控件且没有填充
一切都应该有填充甚至逻辑控件(容器),对吧?我认为这是不一致的。您怎么看?
如果您通过ListBox
将焦点设置为FocusManager.FocusedElement
,您仍然无法通过键盘切换内容,因为焦点设置为{{1} es es不是它的内容。我想我不知道其他UI API会向UI程序员公开类似控件框架的东西它应该从我们这里封装,因为抽象的ListBox代表一个列表,它只是一个列表,而不是一个盒子里的东西列表。 好吧它的名字中有盒子但仍然...... 我们这里几乎有两个不同的控件。
MVVM not breaking fix
ListBox
为ListBox.IsSynchronizedWithCurrentItem
,因此如果您为false
指定了不同的值或null
,那么ItesSource
仍会保留旧值,直到用户选择来自新名单的东西。例如,它可能会弄乱SelectedItem
。需要每次手动设置。
CanExecute
中没有暴露绑定会导致时间浪费和肮脏的黑客攻击......但它仍有一个字符串属性PasswordBox
暴露,所以甚至不要试图争论安全性因为Snoop ......
这不是问题,但是表格布局是如此IE6 IMO。容器设计有助于将内容与其布局分开
因为每次我需要在某些地方更改某些内容时,我都需要使用PasswordBox.Password
和Grid.Row
。是的,我们有Grid.Column
,DockPanel
和其他人,但您无法在其中进行一些列对齐。 (而且StackPanel
就像完全独立的问题一样)如果DockPanel
可以更加自定义,那么我认为这是理想的。你总是需要在网格和面板之间进行选择,通常如果你获得了一些东西,你就会失去其他东西。
答案 5 :(得分:1)
上周我非常精彩:
模板化RichTextBox时,模板内部的事件处理遵循一条奇怪的路线,既没有隧道也没有冒泡
例如:对于应该隧道的事件:事件首先通过ContentPresenter隧道,然后从模板顶部隧道返回。
答案 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