Ошибка привязки для ListView UserControls - PullRequest
0 голосов
/ 23 января 2019

Я пытаюсь создать просмотр списка с каждым элементом просмотра списка отдельным пользовательским элементом управления.

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 связывает 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 - это UserControl.Я получаю следующую ошибку привязки:

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

И для полноты, вот xaml для Usercontrol, с которым я работаю:

<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 голосов
/ 23 января 2019
public class main
{
    DataClass dc = new DataClass();
    public void yourinitialmethod()
    {
        InitializeComponents();
        this.DataContext = dc;
    }
}

Не используйте ElementName=... в вашем XAML и лучше используйте глобальный (оконный) DataContext.Его глубина DataContext автоматически увеличивается до самого контейнера элемента (который в этом случае не нужен)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...