【发布时间】:2013-03-20 21:27:18
【问题描述】:
有人可以解释一下这个错误吗?
一开始我以为 SelectedIndex 可能只是不是 DependencyProperty 不能绑定,但我错了。
如果我使用普通绑定而不是标记扩展 src:ValidatedBinding,或者如果我保留标记扩展但绑定 SelectedItem 而不是 SelectedIndex,那么它可以工作。
这是一个演示问题的小应用程序。
主窗口:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:src="clr-namespace:WpfApplication2"
Title="MainWindow"
Height="350"
Width="525"
>
<ComboBox SelectedIndex="{src:ValidatedBinding SelectedIndex}"
VerticalAlignment="Center" HorizontalAlignment="Center" Width="100">
<ComboBoxItem>Not Specified</ComboBoxItem>
<ComboBoxItem>First</ComboBoxItem>
<ComboBoxItem>Second</ComboBoxItem>
</ComboBox>
</Window>
主窗口后面的代码:
using System.Windows;
namespace WpfApplication2
{
/// <summary>
/// The main window.
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new Item { Description = "Item 1", SelectedIndex = 0 };
}
}
/// <summary>
/// An object with a string and an int property.
/// </summary>
public sealed class Item
{
int _selectedIndex;
string _description;
public string Description
{
get { return _description; }
set { _description = value; }
}
public int SelectedIndex
{
get { return _selectedIndex; }
set { _selectedIndex = value; }
}
}
}
标记扩展的代码:
using System;
using System.Windows;
using System.Windows.Data;
using System.Windows.Markup;
namespace WpfApplication2
{
/// <summary>
/// Creates a normal Binding but defaults NotifyOnValidationError and
/// ValidatesOnExceptions to True, Mode to TwoWay and UpdateSourceTrigger
/// to LostFocus.
/// </summary>
[MarkupExtensionReturnType(typeof(Binding))]
public sealed class ValidatedBinding : MarkupExtension
{
public ValidatedBinding(string path)
{
Mode = BindingMode.TwoWay;
UpdateSourceTrigger = UpdateSourceTrigger.LostFocus;
Path = path;
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
var Target = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
/* on combo boxes, use an immediate update and validation */
DependencyProperty DP = Target.TargetProperty as DependencyProperty;
if (DP != null && DP.OwnerType == typeof(System.Windows.Controls.Primitives.Selector)
&& UpdateSourceTrigger == UpdateSourceTrigger.LostFocus) {
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
}
return new Binding(Path) {
Converter = this.Converter,
ConverterParameter = this.ConverterParameter,
ElementName = this.ElementName,
FallbackValue = this.FallbackValue,
Mode = this.Mode,
NotifyOnValidationError = true,
StringFormat = this.StringFormat,
ValidatesOnExceptions = true,
UpdateSourceTrigger = this.UpdateSourceTrigger
};
}
public IValueConverter Converter { get; set; }
public object ConverterParameter { get; set; }
public string ElementName { get; set; }
public object FallbackValue { get; set; }
public BindingMode Mode { get; set; }
[ConstructorArgument("path")]
public string Path { get; set; }
public string StringFormat { get; set; }
public UpdateSourceTrigger UpdateSourceTrigger { get; set; }
}
}
我运行此应用程序时的异常:
发生 System.Windows.Markup.XamlParseException
HResult=-2146233087 Message='设置属性 'System.Windows.Controls.Primitives.Selector.SelectedIndex' 抛出了一个 异常。'行号'9'和行位置'19'。
来源=PresentationFramework LineNumber=9 LinePosition=19
堆栈跟踪: 在 System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader,IXamlObjectWriterFactory writerFactory,布尔 skipJournaledProperties、对象 rootObject、XamlObjectWriterSettings 设置,Uri baseUri) 在 System.Windows.Markup.WpfXamlLoader.LoadBaml(XamlReader xamlReader,布尔型 skipJournaledProperties,对象 rootObject, XamlAccessLevel accessLevel, Uri baseUri) 在 System.Windows.Markup.XamlReader.LoadBaml(流流,ParserContext parserContext,对象父,布尔 closeStream) 在 System.Windows.Application.LoadComponent(对象组件,Uri 资源定位器) 在 c:\Users\Administrator\Documents\Visual Studio 中的 WpfApplication2.MainWindow.InitializeComponent() 2012\Projects\WpfApplication2\MainWindow.xaml:第 1 行 在 c:\Users\Administrator\Documents\Visual Studio 中的 WpfApplication2.MainWindow..ctor() 2012\Projects\WpfApplication2\MainWindow.xaml.cs:第 12 行
内部异常:System.ArgumentException H结果=-2147024809 Message='System.Windows.Data.Binding' 不是属性“SelectedIndex”的有效值。 源=WindowsBase 堆栈跟踪: 在 System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, 对象值、PropertyMetadata 元数据、布尔值 coerceWithDeferredReference,布尔 coerceWithCurrentValue, OperationType operationType, Boolean isInternal) 在 System.Windows.DependencyObject.SetValue(DependencyProperty dp,对象 价值) 在 System.Windows.Baml2006.WpfMemberInvoker.SetValue(对象实例, 对象值) 在 MS.Internal.Xaml.Runtime.ClrObjectRuntime.SetValue(XamlMember 成员, 对象 obj,对象值) 在 MS.Internal.Xaml.Runtime.ClrObjectRuntime.SetValue(对象实例, XamlMember 属性,对象值) 内部异常:
【问题讨论】:
-
SelectedIndex是一个int。您不能将System.Windows.Data.Binding放在int属性中。你的MarkupExtension是错误的。您正在返回Binding本身,而不是评估它并返回Binding Source。 -
@HighCore - 但是普通的
{Binding xxx}也不是int。我不明白。如果我使用{Binding SelectedIndex}而不是{src:ValidatedBinding SelectedIndex}那么它会起作用,并且基本上都返回一个绑定。我在哪里错过了船? -
Binding标记扩展不返回Binding实例,它创建绑定并返回另一端(源)中的值 -
@HighCore - 谢谢你的解释。这是有道理的,除了标记扩展适用于
SelectedItem。SelectedItem是否忽略绑定并改为分配值? -
SelectedItem的类型为object,这就是为什么您没有收到异常,但这并不意味着它正在工作。不是,您只是将Binding类的一个实例分配给SelectedItem属性。
标签: c# wpf combobox selectedindex markup-extensions