我试图从我的用户控件绑定到我的用户控件的依赖项属性,但它似乎没有工作,因为转换器不断抛出未设置的依赖项属性错误
依赖属性
public DateTime? DisplayedDate
{
get { return (DateTime?)base.GetValue(DisplayedDateProperty); }
set { base.SetValue(DisplayedDateProperty, value); }
}
public static readonly DependencyProperty DisplayedDateProperty =
DependencyProperty.Register("DisplayedDate", typeof(DateTime?), typeof(SideBarUser), new FrameworkPropertyMetadata()
{
BindsTwoWayByDefault = true,
DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
});
XAML绑定
<UserControl.Resources>
<sys:Int32 x:Key="Test">1</sys:Int32>
<Converters:DateCountConverter x:Key="DateCountConverter"/>
</UserControl.Resources>
<TextBlock DataContext="{Binding RelativeSource={RelativeSource Self}}"
TextAlignment="Center">
<TextBlock.Text>
<MultiBinding Converter="{StaticResource DateCountConverter}">
<Binding Path="DisplayedDate" />
<Binding Source="{StaticResource Test}" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
最后,它在变形器中失败的部分
DateTime date = (DateTime)values[0];
共同产生
System.InvalidCastException
Specified cast is not valid.
at System.Windows.Data.MultiBindingExpression.TransferValue()
at System.Windows.Data.MultiBindingExpression.Transfer()
at System.Windows.Data.MultiBindingExpression.UpdateTarget(Boolean includeInnerBindings)
at System.Windows.Data.MultiBindingExpression.AttachToContext(Boolean lastChance)
at System.Windows.Data.MultiBindingExpression.MS.Internal.Data.IDataBindEngineClient.AttachToContext(Boolean lastChance)
at MS.Internal.Data.DataBindEngine.Task.Run(Boolean lastChance)
at MS.Internal.Data.DataBindEngine.Run(Object arg)
at MS.Internal.Data.DataBindEngine.OnLayoutUpdated(Object sender, EventArgs e)
at System.Windows.ContextLayoutManager.fireLayoutUpdateEvent()
at System.Windows.ContextLayoutManager.UpdateLayout()
at System.Windows.UIElement.UpdateLayout()
at System.Windows.Interop.HwndSource.SetLayoutSize()
at System.Windows.Interop.HwndSource.set_RootVisualInternal(Visual value)
at System.Windows.Interop.HwndSource.set_RootVisual(Visual value)
at MS.Internal.DeferredHwndSource.ProcessQueue(Object sender, EventArgs e)
我似乎无法让这一切为我的生活而工作。我错过了什么吗?使用另一个Visual Studio实例进行调试时,会发现它是Unset Dependency属性
编辑: 当我评论所有内容并且只是
<TextBlock Text="{Binding Path=DisplayedDate, RelativeSource={RelativeSource Self}}" />
它可以很好地显示显示日期。我的混乱程度太大,无法立即应对
编辑编辑: 转换器代码
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
DateTime? date = (DateTime?)values[0];
//ToDo move most of the logic inside AppointmentsViewModel class to handle date filtering
AppointmentsViewModel MyAppointments = new AppointmentsViewModel();
String Count;
int SelectionType = (int)values[1];
//Note To Self Make Enum
switch (SelectionType)
{
case 0:
Count = MyAppointments.Appointments.Where(x => date != null && x.Beginning.HasValue && date.HasValue
&& x.Beginning.Value.Month == date.Value.Month
&& x.Beginning.Value.Year == date.Value.Year ).Count().ToString();
break;
case 1:
Count = MyAppointments.Appointments.Where(x => date != null && x.Test.HasValue && date.HasValue
&& x.Test.Value.Month == date.Value.Month
&& x.Test.Value.Year == date.Value.Year).Count().ToString();
break;
//ETC
default:
Count = MyAppointments.Appointments.Where(x => date != null && x.End.HasValue
&& date.HasValue && x.End.Value.Month == date.Value.Month
&& x.End.Value.Year == date.Value.Year).Count().ToString();
break;
}
return Count;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
答案 0 :(得分:2)
您的代码存在一些问题。我不得不在这里做一些假设,所以希望我是对的。
转换器
您的转换器假定它将获得某些类型的2个值。你想要小心一点。特别是第一个来自绑定的值,如果尚未设置绑定,则可能是DependencyProperty.UnsetValue
。
因此,您可能希望在开始实际转换之前检查值是否正确,例如:
if (values.Length != 2 || !(values[0] is DateTime?)|| !(values[1] is int))
{
return DependencyProperty.UnsetValue;
}
您不应该让转换器抛出异常,因为它们被视为未捕获的运行时异常,并且将终止您的应用程序,除非您有一些全局异常处理程序(请参阅this question)。
控件
现在,我假设您的DisplayedDate
属性已定义在UserControl
上。如果是这样,那么这一行:
<TextBlock DataContext="{Binding RelativeSource={RelativeSource Self}}"
会将DataContext
设置为此TextBlock
,因此当您稍后检索DisplayedDate
属性时,将无法找到它。您可以通过两种方式解决此问题:
1)您使用祖先查找绑定:
"{Binding RelativeSource={RelativeSource AncestorType=local:UserControl1}}"
当然,将local:UserControl1
替换为控件的名称空间和名称。
2)您将UserControl
的内容定义为模板,然后使用{RelativeSource TemplatedParent}
,它将指向模板的“所有者”,在本例中为{{1} }:
UserControl
只需将其放入XAML而不是<UserControl.Template>
<ControlTemplate>
<TextBlock DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}"
TextAlignment="Center">
<TextBlock.Text>
<MultiBinding Converter="{StaticResource DateCountConverter}">
<Binding Path="DisplayedDate" />
<Binding Source="{StaticResource Test}" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</ControlTemplate>
</UserControl.Template>
... <TextBlock>
部分。
也许还有一些其他问题,但是使用简单的转换器进行测试对我有用。