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

时间:2015-04-30 22:02:09

标签: c# wpf dependency-properties

我试图从我的用户控件绑定到我的用户控件的依赖项属性,但它似乎没有工作,因为转换器不断抛出未设置的依赖项属性错误

依赖属性

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

1 个答案:

答案 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>部分。

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