取消对绑定到依赖项的依赖项 属性

Unset dependency on binding to 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,
      });

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 的另一个实例进行调试时,出现它是一个未设置的依赖项 属性

编辑: 当我注释掉所有内容并且只有

<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();
            }

您的代码有几个问题。我不得不在这里做出一些假设,所以希望我是正确的。

转换器

您的转换器假定它将获得某些类型的 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},它将指向模板的 "owner",在这种情况下,您的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>

只需将其放入 XAML 而不是 <TextBlock>...</TextBlock> 部分。

也许还有一些其他问题,但使用一个简单的转换器进行测试这对我有用。