用户控件的ListView的绑定错误

时间:2019-01-22 21:28:09

标签: c# wpf

我试图用每个单独的用户控件创建一个listview。

MainPage.xaml:

<ListView Name="Shortcut_Holder"
        ScrollViewer.VerticalScrollBarVisibility="Disabled"
        ScrollViewer.HorizontalScrollBarVisibility="Disabled"
        SelectionMode="Single"
        SelectedIndex="-1"
        HorizontalContentAlignment="Stretch"
        ItemsSource="{Binding ShortcutList,
                            UpdateSourceTrigger=PropertyChanged,
                            ElementName=MainPage}">


    <ListView.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal" />
        </ItemsPanelTemplate>
    </ListView.ItemsPanel>


    <ListView.ItemContainerStyle>
        <Style TargetType="{x:Type ListViewItem}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type ListViewItem}">
                        <local:Exam_Folder />
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Setter Property="HorizontalContentAlignment" Value="Stretch" />
        </Style>
    </ListView.ItemContainerStyle>

</ListView>

ShortcutList在页面的代码中绑定了自定义Usercontrol的ObservableCollection。该页面实现INotifyPropertyChange,并且在应用程序中的另一个事件上,将填充该集合。

MainPage.xaml.cs:

public ObservableCollection<Exam_Folder> ShortcutList
{
     get => _shortcutlist;
     set
     {
         _shortcutlist = value;
         _shortcutdataview = new CollectionViewSource();
         _shortcutdataview.Source = _shortcutlist;

         NotifyPropertyChanged("ShortcutList");
     }
}

private ObservableCollection<Exam_Folder> _shortcutlist { get; set; }

public ListCollectionView ShortCutDataView
{
    get => (ListCollectionView)_shortcutdataview.View;
}
private CollectionViewSource _shortcutdataview { get; set; }

private void HandleExamListUpdate()
{
    //Make shortcut list a new observable collection of 
    exam_folders
    ShortcutList = new ObservableCollection<Exam_Folder>(CreateExamFolderUIList());
    var view = (ListCollectionView)CollectionViewSource.GetDefaultView(ShortcutList);
    view.CustomSort = new Exam_Folder_Comparer(((MainViewModel)DataContext).CurrentExamShortcutSort);
}

其中Exam_Folder是用户控件。我收到以下绑定错误:

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ItemsControl', AncestorLevel='1''. BindingExpression:Path=HorizontalContentAlignment; DataItem=null; target element is 'ListViewItem' (Name=''); target property is 'HorizontalContentAlignment' (type 'HorizontalAlignment')

之后,应用程序崩溃。我对WPF还是很陌生,因此我尽力了。有什么想法吗?

编辑:

我现在将列表视图绑定到数据,而不是用户控件。我以为这可以解决我所遇到的错误,但是现在该错误有时会出现...我想说我有50%的时间运行该应用程序,但仍然崩溃了。

MainPage.xaml:

                <!-- Listview ItemsSource needs to be bound to page since it's a collection of User Controls-->
                <ListView Name="Shortcut_Holder"
                          ScrollViewer.VerticalScrollBarVisibility="Disabled"
                          ScrollViewer.HorizontalScrollBarVisibility="Disabled"
                          SelectionMode="Single"
                          SelectedIndex="-1"
                          SelectionChanged="Shortcut_Holder_SelectionChanged"
                          Background="Transparent"
                          BorderBrush="Transparent"
                          ItemsSource="{Binding ShortcutList,
                                                UpdateSourceTrigger=PropertyChanged,
                                                ElementName=MainPage}">

                    <ListView.Resources>
                        <Style TargetType="{x:Type ListViewItem}">
                            <Setter Property="Background" Value="Transparent" />
                        </Style>
                    </ListView.Resources>

                    <!-- How Listview items are laid out -->
                    <ListView.ItemsPanel>
                        <ItemsPanelTemplate>
                            <StackPanel Orientation="Horizontal" />
                        </ItemsPanelTemplate>
                    </ListView.ItemsPanel>

                    <!-- Data Template for each listview item-->
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <local:Exam_Folder DisplayText="{Binding Converter={local:ExamShortcutDisplayTextValueConverter}}" />
                        </DataTemplate>
                    </ListView.ItemTemplate>

                    <!-- Style for each listview item -->
                    <ListView.ItemContainerStyle>
                        <Style TargetType="{x:Type ListViewItem}">
                            <Setter Property="Padding" Value="0" />
                            <Setter Property="Background" Value="Transparent" />
                            <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                            <Setter Property="Margin" Value="5,0,5,0" />
                            <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="{x:Type ListViewItem}">
                                        <ContentPresenter />
                                    </ControlTemplate>
                                </Setter.Value>
                            </Setter>

                            <!-- Change cursor style over each list item on mouse hover -->
                            <Style.Triggers>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter Property="ForceCursor" Value="True" />
                                    <Setter Property="Cursor" Value="Hand" />
                                </Trigger>
                            </Style.Triggers>

                        </Style>
                    </ListView.ItemContainerStyle>

                </ListView>

MainPage.xaml.cs:

private void HandleExamListUpdate(bool RefreshList = true)
    {
        //Make shortcut list a new observable collection of exam_folders
        if (ShortcutList == null || ShortcutList.Count == 0 || RefreshList)
            ShortcutList = new ObservableCollection<ExamType>(Ioc.Get<ApplicationViewModel>().CurrentPatient.PatientExams);

        var view = (ListCollectionView)CollectionViewSource.GetDefaultView(ShortcutList);
        view.CustomSort = new Exam_Folder_Comparer(((MainViewModel)DataContext).CurrentExamShortcutSort);

        //Calculate how many folders can be displayed given the width of the control
        //If there has been no change in the amount of exam folders we need to display, no need to do anything else
        //Have to do math on the overall top grid, bc the stackpanel that holds the folders would initially have its actualwidth skewed by the 
        //possible amount of controls in it.
        int holdingnumber = (int)(Math.Ceiling((Top_View.ActualWidth - TopCol1.ActualWidth - TopCol3.ActualWidth) / WIDTH_PER_SHORTCUT));

        //Apply filter based on the amount of controls we can hold
        view.Filter = new Predicate<object>(o =>
        {
            if (ShortcutList.IndexOf((ExamType)o) < holdingnumber)
                return true;

            return false;
        });
    }

为了完整起见,这是我正在使用的Usercontrol的xaml:

<UserControl x:Class="Tomo_GUI.Exam_Folder"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:Tomo_GUI"
         xmlns:svgc="http://sharpvectors.codeplex.com/svgc/"
         mc:Ignorable="d" 
         Background="Transparent"
         d:DesignHeight="100" d:DesignWidth="120">

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="*" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>

    <svgc:SvgViewbox Grid.RowSpan="3">

        <svgc:SvgViewbox.Style>
            <Style TargetType="svgc:SvgViewbox">
                <Setter Property="local:SvgcViewboxAttachedProperties.Source" Value="{Binding ImagePath, 
                                                                                              RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" />
                <Style.Triggers>
                    <DataTrigger Binding="{Binding IsMouseOver,
                                                   RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
                                 Value="True">
                        <Setter Property="local:SvgcViewboxAttachedProperties.Source" Value="\Images\TopView\Exam_File_Icon_Colored.svg" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </svgc:SvgViewbox.Style>

    </svgc:SvgViewbox>

    <TextBlock FontSize="{StaticResource FontSizeRegularSmall}"
               FontWeight="Black"
               Grid.Row="1"
               VerticalAlignment="Center"
               HorizontalAlignment="Center"
               Background="Transparent"
               Text="{Binding DisplayText,
                              RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
               Name="BlockText">
    </TextBlock>

</Grid>

现在,当最初加载集合时,有时会出现相同的错误;或者,如果我更改集合上的过滤器,有时会出现相同的错误。有什么想法会发生什么吗?

1 个答案:

答案 0 :(得分:-1)

public class main
{
    DataClass dc = new DataClass();
    public void yourinitialmethod()
    {
        InitializeComponents();
        this.DataContext = dc;
    }
}

请勿在XAML中使用ElementName=...,而最好使用全局(窗口)DataContext。 它的DataContext深度会自动持续到项目容器本身(在这种情况下不需要它)