简体   繁体   English

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM