绑定在 ListView 中不起作用

发布于 2024-09-05 12:18:59 字数 4971 浏览 2 评论 0原文

我有一个名为 DataPicker 的 wpf 控件,它有一个名为 SelectedDate 的依赖属性。

在简单的情况下,它工作得很好,但有一种情况绑定失败,我不明白为什么:当我尝试将它绑定到 ListView 内时。

例如,我有一个类(INotifyPropertyChanged 已实现)

public class TestClass : INotifyPropertyChanged
{
    public string Name { get; set; }
    public DateTime Date { get; set; }
}

并尝试绑定示例集合,就像

public ObservableCollection<TestClass> Items { get; set; }

其中包含一个元素一样。

绑定看起来像

 <Window x:Class="Neverov.Test.Window1"
         x:Name="this"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:local="clr-namespace:Neverov.Framework;assembly=Neverov.Framework">
     <Grid>        
         <ListView ItemsSource="{Binding ElementName=this, Path=Items}">
             <ListView.ItemTemplate>
                 <DataTemplate>                     
                     <StackPanel>
                         <TextBlock Text="{Binding Name}"/>
                             <local:DatePicker SelectedDate="{Binding Date, Mode=TwoWay}"/>                             
                     </StackPanel>                     
                 </DataTemplate>
             </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Window>

并且 Name 属性工作正常。

我的 DatePicker 日期值内部显示如下:

<TextBox x:Name="PART_TextBox">
    <TextBox.Text>
        <Binding Path="SelectedDate" 
                 RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type local:DatePicker}}"
                 Mode="TwoWay"
                 Converter="{StaticResource DateTimeConverter}"
                 ConverterParameter="d">
        </Binding>
    </TextBox.Text>    
</TextBox>

任何想法为什么会发生这种情况?

DatePicker 类的更多代码:(我宁愿错过一些我需要的特定属性,以保持代码大小不那么大)

[TemplatePart(Name = PartPopup, Type = typeof(Popup))]
[TemplatePart(Name = PartMonthBack, Type = typeof(ButtonBase))]
[TemplatePart(Name = PartMonthForward, Type = typeof(ButtonBase))]
[TemplatePart(Name = PartDates, Type = typeof(Selector))]
[TemplatePart(Name = PartTextBox, Type = typeof(TextBox))]
[TemplatePart(Name = PartCheckBox, Type = typeof(CheckBox))]
[TemplatePart(Name = PartToggleButton, Type = typeof(ToggleButton))]
public class DatePicker : Control, INotifyPropertyChanged
{
    ...
    public static readonly DependencyProperty SelectedDateProperty =
        DependencyProperty.Register("SelectedDate",
                                    typeof(DateTime?),
                                    typeof(DatePicker),
                                    new FrameworkPropertyMetadata(null,
                                                                  FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                                                                  (sender, e) =>
                                                                  {
                                                                      var datePicker = sender as DatePicker;
                                                                      if (datePicker != null)
                                                                      {
                                                                          var oldValue = e.OldValue as DateTime?;
                                                                          DateTime selectedDateForPopup =
                                                                              datePicker.SelectedDate ??
                                                                              DateTime.Now;
                                                                          datePicker.CurrentlyViewedMonth =
                                                                              selectedDateForPopup.Month;
                                                                          datePicker.CurrentlyViewedYear =
                                                                              selectedDateForPopup.Year;
                                                                          datePicker.OnDateChanged(datePicker.SelectedDate, oldValue);                                                                              
                                                                          var popup = datePicker.GetTemplateChild(PartPopup) as Popup;
                                                                          if (popup != null)
                                                                              popup.IsOpen = false;
                                                                      }
                                                                  }));
   ... //a lot more not so important code here
}

I have a wpf control named DataPicker which has a dependency property named SelectedDate.

In simple cases it works well but there is one case where binding fails and I can't understand why: when i try to bind it inside a ListView.

For example, I have class (INotifyPropertyChanged is implemented)

public class TestClass : INotifyPropertyChanged
{
    public string Name { get; set; }
    public DateTime Date { get; set; }
}

and try to bind sample collection like

public ObservableCollection<TestClass> Items { get; set; }

which has one element in it.

Binding looks like

 <Window x:Class="Neverov.Test.Window1"
         x:Name="this"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:local="clr-namespace:Neverov.Framework;assembly=Neverov.Framework">
     <Grid>        
         <ListView ItemsSource="{Binding ElementName=this, Path=Items}">
             <ListView.ItemTemplate>
                 <DataTemplate>                     
                     <StackPanel>
                         <TextBlock Text="{Binding Name}"/>
                             <local:DatePicker SelectedDate="{Binding Date, Mode=TwoWay}"/>                             
                     </StackPanel>                     
                 </DataTemplate>
             </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Window>

and Name property works fine.

inside my DatePicker date value is shown this way:

<TextBox x:Name="PART_TextBox">
    <TextBox.Text>
        <Binding Path="SelectedDate" 
                 RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type local:DatePicker}}"
                 Mode="TwoWay"
                 Converter="{StaticResource DateTimeConverter}"
                 ConverterParameter="d">
        </Binding>
    </TextBox.Text>    
</TextBox>

any ideas why this could happen?

More code of the DatePicker class: (some specific properties that I need I'll rather miss to keep code size not so large)

[TemplatePart(Name = PartPopup, Type = typeof(Popup))]
[TemplatePart(Name = PartMonthBack, Type = typeof(ButtonBase))]
[TemplatePart(Name = PartMonthForward, Type = typeof(ButtonBase))]
[TemplatePart(Name = PartDates, Type = typeof(Selector))]
[TemplatePart(Name = PartTextBox, Type = typeof(TextBox))]
[TemplatePart(Name = PartCheckBox, Type = typeof(CheckBox))]
[TemplatePart(Name = PartToggleButton, Type = typeof(ToggleButton))]
public class DatePicker : Control, INotifyPropertyChanged
{
    ...
    public static readonly DependencyProperty SelectedDateProperty =
        DependencyProperty.Register("SelectedDate",
                                    typeof(DateTime?),
                                    typeof(DatePicker),
                                    new FrameworkPropertyMetadata(null,
                                                                  FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                                                                  (sender, e) =>
                                                                  {
                                                                      var datePicker = sender as DatePicker;
                                                                      if (datePicker != null)
                                                                      {
                                                                          var oldValue = e.OldValue as DateTime?;
                                                                          DateTime selectedDateForPopup =
                                                                              datePicker.SelectedDate ??
                                                                              DateTime.Now;
                                                                          datePicker.CurrentlyViewedMonth =
                                                                              selectedDateForPopup.Month;
                                                                          datePicker.CurrentlyViewedYear =
                                                                              selectedDateForPopup.Year;
                                                                          datePicker.OnDateChanged(datePicker.SelectedDate, oldValue);                                                                              
                                                                          var popup = datePicker.GetTemplateChild(PartPopup) as Popup;
                                                                          if (popup != null)
                                                                              popup.IsOpen = false;
                                                                      }
                                                                  }));
   ... //a lot more not so important code here
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

荭秂 2024-09-12 12:19:02

检查输出窗口是否有任何数据绑定错误。

可能的错误:

  • DataContext 设置不正确。
  • ListView ItemsSource="{Binding ElementName=this, Path=Items} Items 不是 Window 或 ViewModel 类的属性吗?

Check the output window for any data binding errors..

Probable errors:

  • DataContext not set correctly.
  • ListView ItemsSource="{Binding ElementName=this, Path=Items} Isn't Items a property of the Window or a ViewModel class ?
無心 2024-09-12 12:19:02

问题解决了。

它不是错误的绑定或其他困难和不均匀的东西,但是,由于它是遗留代码,代码程序员在代码中的某个地方犯了错误。

谢谢大家!

The problem is solved.

It was not in wrong bindings or other difficult and uneven stuff, but, as it was legacy code, somewhere in code programmer made a mistake.

Thank for all!

救星 2024-09-12 12:19:00

确保您的属性抛出 INotifyPropertyChanged 事件:

public class TestClass : INotifyPropertyChanged
{
    private DateTime date;

    public DateTime Date 
    { 
        get { return date; }
        set { date = value; NotifyPropertyChanged("Date"); } 
    }

    private void NotifyPropertyChanged(string info)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }   
}

并使您的日期绑定也为 TwoWay:

<local:DatePicker SelectedDate="{Binding Date, Mode=TwoWay}"/>

Make sure your properties throw the INotifyPropertyChanged event:

public class TestClass : INotifyPropertyChanged
{
    private DateTime date;

    public DateTime Date 
    { 
        get { return date; }
        set { date = value; NotifyPropertyChanged("Date"); } 
    }

    private void NotifyPropertyChanged(string info)
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }   
}

And make your binding to the date also TwoWay:

<local:DatePicker SelectedDate="{Binding Date, Mode=TwoWay}"/>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文