wpf - ошибка привязки RelativeSource ActualWidth, когда добавленный пользовательский контроль не находится в области отображения ListView - PullRequest
0 голосов
/ 08 июля 2019

Я не смог найти решение этой проблемы в интернете.Может кто-нибудь, пожалуйста, предложите мне исправить эту проблему.Ваша помощь очень ценится!

Со ссылкой на следующий форум MSDN: https://social.msdn.microsoft.com/Forums/vstudio/en-US/fb882b44-dee0-41de-a10c-819de9a53f1a/force-a-usercontrols-width-to-stretch-to-parent-container-width?forum=wpf

Я попытался установить ширину UserControl в ActualWidth Listview в Mainwindow.

<UserControl ...
         Width="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListView}}, Path=ActualWidth}">

В главном окне я добавил код для добавления пользовательских элементов управления в ListView при нажатии кнопки через привязку команды ViewModel.

        UserControl1 uc1 = new UserControl1();
        ViewCollection.Add(uc1);

Что я заметил, если пользовательский контроль добавляется в область отображения ListView,затем создается пользовательский контроль с шириной, растянутой до ширины ListView.Также этот usercontrol всегда изменяется до ширины ListView при изменении размера окна.

Но если usercontrol добавляется в неотображаемую область ListView (когда полоса прокрутки не прокручивается там, где добавлен UserControl), тогда usercontrolсоздается с его оригинальной определенной шириной, и пользовательский контроль не изменяет размер до ширины списка.Также я вижу ошибку привязки в OutputWindow (Debug):

System.Windows.Data Ошибка: 4: не удается найти источник для привязки со ссылкой 'RelativeSource FindAncestor, AncestorType =' System.Windows.Controls.ListView ', AncestorLevel = '1' '.BindingExpression: Path = ActualWidth;DataItem = NULL;целевым элементом является 'UserControl1' (Name = '');Свойство target - «Width» (тип «Double»)

<UserControl x:Class="BindingUCWidth.UserControl1"
         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" 
         mc:Ignorable="d"
         Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListView},
                Path=ActualWidth}">
    <Grid>
        <GroupBox Header="User Control 1">
            <StackPanel Orientation="Vertical">
                <Button Content="hello1" Width="Auto"/>
                <Button Content="hello2" Width="Auto"/>
            </StackPanel>
        </GroupBox>
    </Grid>
</UserControl>

<Window x:Class="BindingUCWidth.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:BindingUCWidth"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="30"/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="1*"/>
        <ColumnDefinition Width="1*"/>
    </Grid.ColumnDefinitions>
    <Button Grid.Row="0" Grid.Column="0" Content="Add UC 1" Command="{Binding AddUC1Command}"/>
    <Button Grid.Row="0" Grid.Column="1" Content="Add UC 2" Command="{Binding AddUC2Command}"/>
    <ListView x:Name="ViewsList" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" ItemsSource="{Binding ViewCollection}"
            BorderBrush="Black" BorderThickness="1,1,1,1" Margin="1"
            HorizontalAlignment="Stretch" VerticalAlignment="Stretch" 
            HorizontalContentAlignment="Stretch" VerticalContentAlignment="Bottom"
            ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Visible">
        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Setter Property="Focusable" Value="True"/>
                <Setter Property="HorizontalAlignment" Value="Left"/>
                <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
            </Style>
        </ListView.ItemContainerStyle>
    </ListView>
</Grid>

using System;
using System.Windows.Input;

namespace BindingUCWidth
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        MainViewModel mvm = new MainViewModel();
        this.DataContext = mvm;
    }
}

public class MainViewModel
{
    public ObservableCollection<UserControl> ViewCollection { get; set; }
    public ICommand AddUC1Command { get; set; }
    public ICommand AddUC2Command { get; set; }

    public MainViewModel()
    {
        ViewCollection = new ObservableCollection<UserControl>();
        AddUC1Command = new RelayCommand(param => AddUC1RelayCommand());
        AddUC2Command = new RelayCommand(param => AddUC2RelayCommand());
    }

    private void AddUC1RelayCommand()
    {
        UserControl1 uc1 = new UserControl1();
        ViewCollection.Add(uc1);
    }

    private void AddUC2RelayCommand()
    {
        UserControl2 uc2 = new UserControl2();
        ViewCollection.Add(uc2);
    }
}

public class RelayCommand : ICommand

{
    private Action<object> execute;
    private Func<object, bool> canExecute;

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
    {
        this.execute = execute;
        this.canExecute = canExecute;
    }

    public bool CanExecute(object parameter)
    {
        return this.canExecute == null || this.canExecute(parameter);
    }

    public void Execute(object parameter)
    {
        this.execute(parameter);
    }
}
}

Прикрепленные файлы изображений.

Размер UserControl изменен должным образом - случай 1 UserControl не изменен, ошибка привязки - случай 2

1 Ответ

0 голосов
/ 23 июля 2019

Ответ дал эксперт MSFT.https://social.msdn.microsoft.com/Forums/vstudio/en-US/53ed166e-2236-47b9-a628-350ea3ce122b/wpf-relativesource-actualwidth-binding-error-when-added-usercontrol-is-not-in-display-area-of?forum=wpf

"Это вызвано виртуализацией WPF ListView.

Вы можете отключить виртуализацию ListView для решения этой проблемы.

Установите для VirtualizingStackPanel.IsVirtualizing значение false наListView или установите обычную StackPanel в качестве ListView.ItemsPanel.

 VirtualizingStackPanel.IsVirtualizing="False"

Или:

<ListView.ItemsPanel>
     <ItemsPanelTemplate>
       <StackPanel></StackPanel>
      </ItemsPanelTemplate>
  </ListView.ItemsPanel>

"

...