[英]Unset dependency on binding to dependency property
I am trying to bind to a dependency property of my user control from my user control however it doesn't seem to be working as the converter keeps throwing an unset dependency property error 我正在尝试从我的用户控件绑定到我的用户控件的依赖项属性,但是由于转换器不断抛出未设置的依赖项属性错误,它似乎不起作用
The dependency property 依赖项属性
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,
});
The XAML Binding 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>
And finally the part it's failing at in the coverter 最后是它在掩护中失败的部分
DateTime date = (DateTime)values[0];
All together yields 合计产量
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)
I cannot seem to get this to work for the life of me. 我似乎无法使它在我的一生中发挥作用。 Am I missing something?
我想念什么吗? When debugging with another instance of Visual Studio it comes up that it is an Unset Dependency property
在使用Visual Studio的另一个实例进行调试时,会显示它是“未设置依赖项”属性
Edit: When I comment out everything and just have 编辑:当我注释掉一切,只有
<TextBlock Text="{Binding Path=DisplayedDate, RelativeSource={RelativeSource Self}}" />
It works just fine displaying the display date. 它可以很好地显示显示日期。 My confusion level is too great to cope with right now
我的困惑水平太大,无法应付
EDIT EDIT: Converter code 编辑编辑:转换器代码
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();
}
There are several problems with your code. 您的代码有几个问题。 I had to make some assumptions here, so hopefully I'm correct.
我必须在这里做一些假设,所以希望我是正确的。
The converter 转换器
Your converter assumes that it will get 2 values of certain types. 您的转换器假定它将获得2种特定类型的值。 You want to be a little careful with that.
您需要对此小心一点。 Especially the first value, which comes from a binding, might be
DependencyProperty.UnsetValue
if the binding has not been set yet. 特别是,如果尚未设置绑定,则来自绑定的第一个值可能是
DependencyProperty.UnsetValue
。
So, you probably want to check if the values are correct before you start doing the actual conversion, for example: 因此,您可能想在开始进行实际转换之前检查值是否正确,例如:
if (values.Length != 2 || !(values[0] is DateTime?)|| !(values[1] is int))
{
return DependencyProperty.UnsetValue;
}
You should not have your converter throw exceptions, because they are treated as uncaught run-time exceptions and will terminate your application unless you have some global exception handler (see this question ). 您不应该让您的转换器抛出异常,因为它们被视为未捕获的运行时异常,除非您有一些全局异常处理程序(请参阅此问题 ),否则它们将终止您的应用程序。
The control 控制
Now, I assume that your DisplayedDate
property is defined on your UserControl
. 现在,我假设您的
DisplayedDate
属性是在UserControl
上定义的。 If so, then this line: 如果是这样,则此行:
<TextBlock DataContext="{Binding RelativeSource={RelativeSource Self}}"
will set the DataContext
to this TextBlock
, so when you later go to retrieve the DisplayedDate
property, it will not be found. 会将
DataContext
设置为此TextBlock
,因此当您以后去检索DisplayedDate
属性时,将找不到它。 You can fix this in 2 ways: 您可以通过两种方式解决此问题:
1) You use the ancestor-lookup binding: 1)您使用祖先查找绑定:
"{Binding RelativeSource={RelativeSource AncestorType=local:UserControl1}}"
Of course, replace local:UserControl1
with the namespace and name of your control. 当然,用
local:UserControl1
的名称空间和名称替换local:UserControl1
。
2) You define the content of the UserControl
as a Template instead, then use {RelativeSource TemplatedParent}
, which will point to the "owner" of the template, in this case, your UserControl
: 2)您可以将
UserControl
的内容定义为模板,然后使用{RelativeSource TemplatedParent}
,它指向{RelativeSource TemplatedParent}
的“所有者”,在本例中为UserControl
:
<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>
Just put this in your XAML instead of the <TextBlock>
... </TextBlock>
part. 只需将其放在您的XAML中,而不是
<TextBlock>
... </TextBlock>
部分。
Maybe there are some other issues, but testing with a simple converter this worked for me. 也许还有其他问题,但是使用一个简单的转换器进行测试对我来说很有用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.