如何在交互请求中获取scrollviewer的可滚动高度以进行更新

时间:2017-06-16 06:01:27

标签: c# wpf prism

编辑:我发现实际上滚动查看器中我的项目控件中的项目主持人没有正确更新而不是滚动查看器。我添加了一个答案来反映这一点。

我有一个简单的自定义视图交互请求设置。视图包含滚动查看器,但如果其中的项目控件具有项目源更新,则滚动查看器可滚动高度不会更新。相关代码如下。

确认模型:

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

视图模型:

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

查看:

<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>

似乎项目来源正在更新,我可以看到隐藏在滚动查看器下方的新项目元素,但我无法向下滚动到它。

如何更新可滚动高度?

1 个答案:

答案 0 :(得分:0)

问题不在于滚动查看器。它是滚动查看器中项目控件的项目演示者。它没有更新物品更换的高度。

我的解决方案并不理想,但确实有效。我在后面的代码中为用户控件添加了一个加载的事件处理程序。然后我命名了items控件并使用它找到了presenter子项,并调用了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;
            }