简体   繁体   English

如何获得滚动查看器的可滚动高度以在交互请求中更新

[英]How to get a scrollviewer's scrollable height to update in an interaction request

EDIT: I discovered that it was in fact the items presenter in my items control within the scroll viewer that wasn't updating correctly rather than the scrollviewer. 编辑:我发现实际上是我的项目控件中的项目演示者在滚动查看器中而不是在滚动查看器中没有正确更新。 I added an answer to reflect this. 我添加了一个答案来反映这一点。

I have a simple set up for a custom view interaction request. 我为自定义视图交互请求进行了简单的设置。 The view contains a scroll viewer but the scroll viewers scrollable height doesn't update if the items control within it has an items source update. 该视图包含一个滚动查看器,但是如果滚动查看器中的项目控件具有项目源更新,则滚动查看器的可滚动高度不会更新。 The relevant code is below. 相关代码如下。

Confirmation model: 确认模型:

public class ProfileImportConfirmation : Confirmation
{
    public ObservableCollection<ProfileAcceptPair> PossibleProfiles { get; set; } = new ObservableCollection<ProfileAcceptPair>();
    public ObservableCollection<Profile> ConfirmedProfiles { get; set; } = new ObservableCollection<Profile>();
}

ViewModel: 视图模型:

public class ProfileImportPopupViewModel : BindableBase, IInteractionRequestAware
{
    ProfileImportConfirmation _profileImportConfirmation;

    public InteractionRequest<Confirmation> YesNoConfirmationInteractionRequest { get; }

    public DelegateCommand AcceptCommand { get; set; }
    public DelegateCommand CancelCommand { get; set; }

    public ProfileImportPopupViewModel()
    {
        AcceptCommand = new DelegateCommand(Accept);
        CancelCommand = new DelegateCommand(Cancel);
        YesNoConfirmationInteractionRequest = new InteractionRequest<Confirmation>();
    }

    public INotification Notification
    {
        get { return _profileImportConfirmation; }
        set
        {
            if (value is ProfileImportConfirmation confirmation)
            {
                _profileImportConfirmation = confirmation;
                OnPropertyChanged(nameof(Notification));
            }
        }
    }

    public Action FinishInteraction { get; set; }

    void Cancel()
    {
        _profileImportConfirmation.Confirmed = false;
        FinishInteraction();
    }

    void Accept()
    {
        _profileImportConfirmation.Confirmed = true;
        _profileImportConfirmation.ConfirmedProfiles.Clear();
        _profileImportConfirmation.ConfirmedProfiles.AddRange(_profileImportConfirmation.PossibleProfiles.Where(p => p.Accepted).Select(p => p.Profile).ToList());
        if (_profileImportConfirmation.ConfirmedProfiles.Any(p => p.IsRootProfile))
            YesNoConfirmationInteractionRequest.Raise(
                new Confirmation
                {
                    Title = DisplayStrings.AreYouSureLabel,
                    Content = "Proceed?"
                },
                confirmed => FinishInteraction());
        else
        {
            FinishInteraction();
        }
    }
}

View: 视图:

<UserControl 
         MaxHeight="500"
         MinWidth="400"
         d:DataContext="{d:DesignInstance Type=viewModels:ProfileImportPopupViewModel, IsDesignTimeCreatable=False}"
         Loaded="ProfileImportPopup_OnLoaded">

<i:Interaction.Triggers>
    <mvvm:InteractionRequestTrigger SourceObject="{Binding YesNoConfirmationInteractionRequest, Mode=OneWay}">
        <mvvm:PopupWindowAction IsModal="True" CenterOverAssociatedObject="True" WindowStyle="{StaticResource PopupWindow}" WindowStartupLocation="CenterOwner">
            <mvvm:PopupWindowAction.WindowContent>
                <popups:YesNoConfirmationPopup />
            </mvvm:PopupWindowAction.WindowContent>
        </mvvm:PopupWindowAction>
    </mvvm:InteractionRequestTrigger>
</i:Interaction.Triggers>

<Grid Margin="30, 0, 30, 30">
    <Grid.RowDefinitions>
        <RowDefinition Height="50"/>
        <RowDefinition Height="50"/> 
        <RowDefinition Height="*"/>
        <RowDefinition Height="40"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>

    <Label Grid.ColumnSpan="2" Content="{Binding Notification.Title}" HorizontalAlignment="Left" FontFamily="{StaticResource 'Brandon Grotesque Bold'}" FontSize="{StaticResource LargeFontSize}"/>

    <Label Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Content="{Binding Notification.Content}" HorizontalAlignment="Center" VerticalContentAlignment="Center" FontFamily="{StaticResource 'Brandon Grotesque Bold'}" FontSize="{StaticResource LargeFontSize}"/>

    <ScrollViewer x:Name="aoeu" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" CanContentScroll="True" VerticalScrollBarVisibility="Auto">
        <ItemsControl ItemsSource="{Binding Notification.PossibleProfiles}" Margin="0, 0, 30, 0">
            <ItemsControl.ItemTemplate>
                <DataTemplate DataType="{x:Type models:ProfileAcceptPair}">
                    <CheckBox Style="{StaticResource RightAlignedCheckBox}" Content="{Binding Name}" IsChecked="{Binding Accepted}" HorizontalContentAlignment="Right"/>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </ScrollViewer>

    <Button Grid.Row="3" Grid.Column="0" HorizontalAlignment="Center" Content="{x:Static resources:DisplayStrings.CancelButton}" Style="{StaticResource ModalWindowButton}" Command="{Binding CancelCommand}" Margin="0" VerticalAlignment="Center"/>
    <Button Grid.Row="3" Grid.Column="1" Content="{x:Static resources:DisplayStrings.OKButton}" Style="{StaticResource ModalWindowButton}" Command="{Binding AcceptCommand}" Margin="0" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>

It seems the items source is updating fine and I can see the new item element hidden below the scroll viewer but I can't scroll down to it. 看来item来源正在更新,我可以看到隐藏在滚动查看器下方的新item元素,但无法向下滚动。

How can I get the scrollable height to update? 如何获取可滚动的高度以进行更新?

The problem wasn't with the scroll viewer. 问题不在于滚动查看器。 It was the items presenter from the items control inside the scroll viewer. 它是滚动查看器中项目控件中的项目演示者。 It wasn't updating it's height on items changing. 它不是在更改项目时更新高度。

My solution isn't ideal but it worked. 我的解决方案不是理想的,但是有效。 I added a loaded event handler for the user control in the code behind. 我在后面的代码中为用户控件添加了已加载的事件处理程序。 I then named the items control and using that found the items presenter child and called invalidate measure. 然后,我将项目控件命名为,并使用该控件找到项目展示者子级,并称为无效度量。

void Popup_OnLoaded(object sender, RoutedEventArgs e)
        {
            var itemsPresenter = (ItemsPresenter) FindChild(MyItemsControl, typeof(ItemsPresenter));
            itemsPresenter.InvalidateMeasure();
        }

public DependencyObject FindChild(DependencyObject o, Type childType)
            {
                DependencyObject foundChild = null;
                if (o != null)
                {
                    var childrenCount = VisualTreeHelper.GetChildrenCount(o);
                    for (var i = 0; i < childrenCount; i++)
                    {
                        var child = VisualTreeHelper.GetChild(o, i);
                        if (child.GetType() != childType)
                        {
                            foundChild = FindChild(child, childType);
                        }
                        else
                        {
                            foundChild = child;
                            break;
                        }
                    }
                }
                return foundChild;
            }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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