0

我已经实现了一个 Windows 8 XAML VisibilitySwitchControl,它在特定条件下显示第一个孩子;否则显示其他控件。代码如下

[ContentProperty(Name = "Items")]
public class VisibilitySwitchControl : ItemsControl
{
    public VisibilitySwitchControl()
    {
        DefaultStyleKey = typeof(VisibilitySwitchControl);
        if (Items != null)
            Items.VectorChanged += OnItemsChanged;
    }

    public bool ShowFirst
    {
        get { return (bool)GetValue(ShowFirstProperty); }
        set { SetValue(ShowFirstProperty, value); }
    }

    public static readonly DependencyProperty ShowFirstProperty =
        DependencyProperty.Register("ShowFirst", typeof(bool), typeof(VisibilitySwitchControl), new PropertyMetadata(true, OnShowFirstChanged));

    public object VisibleContent
    {
        get { return GetValue(VisibleContentProperty); }
        private set { SetValue(VisibleContentProperty, value); }
    }

    public static readonly DependencyProperty VisibleContentProperty =
        DependencyProperty.Register("VisibleContent", typeof(object), typeof(VisibilitySwitchControl), new PropertyMetadata(null));

    private static void OnShowFirstChanged(DependencyObject d, DependencyPropertyChangedEventArgs args)
    {
        var visibilityItemsControl = d as VisibilitySwitchControl;
        if (visibilityItemsControl != null)
        {
            visibilityItemsControl.Evaluate();
        }
    }

    void OnItemsChanged(IObservableVector<object> sender, IVectorChangedEventArgs evt)
    {
        Evaluate();
    }

    void Evaluate()
    {
        if (Items != null && Items.Any())
        {
            var controls = Items.OfType<FrameworkElement>().ToList();
            for (var i = 0; i < controls.Count; i++)
            {
                if (i == 0)
                {
                    VisibleContent = controls[i];
                    controls[i].Visibility = ShowFirst ? Visibility.Visible : Visibility.Collapsed;
                }
                else
                {
                    controls[i].Visibility = !ShowFirst ? Visibility.Visible : Visibility.Collapsed;
                }
            }
        }
        else
        {
            VisibleContent = null;
        }
    }
}

ListView但是,如果我在我的 ListView 中放置两个控件VisibilitySwitchControl,它会以比页面大的​​方式增长并且不显示滚动条。它不会停止父容器的界限。

<custom:VisibilitySwitchControl ShowFirst="{Binding Path=IsFirstLevelNav}">
    <ListView x:Name="FirstListView"
            VerticalAlignment="Stretch" 
            ItemsSource="{Binding ...}"
            SelectedItem="{Binding ..., Mode=TwoWay}"
            ScrollViewer.VerticalScrollBarVisibility="Auto" 
            ScrollViewer.HorizontalScrollBarVisibility="Disabled"
            />
    <ListView x:Name="SecondListView"
            VerticalAlignment="Stretch" 
            ItemsSource="{Binding ...}"
            SelectedItem="{Binding ..., Mode=TwoWay}"
            ScrollViewer.VerticalScrollBarVisibility="Auto" 
            ScrollViewer.HorizontalScrollBarVisibility="Disabled"
            />
</custom:VisibilitySwitchControl>

如何强制VerticalAlignment="Stretch"孩子的行为?如果我删除我的控件并直接在代码中放置一个列表,那么一切都会按预期工作。

感谢您的建议。

4

2 回答 2

0

如果您想要的是滚动一个 ListView,然后当您到达末尾时显示第二个 ListView,那么您只需要在 VisibilitySwitchControl 样式内的 ItemPresenter 周围添加一个 ScrollViewer 并禁用 ListView ScrollViewer。请注意,这意味着您将丢失 ListView 中的虚拟化。

如果你想要的是每个 ListView 占据屏幕的一半而不是最简单的可能只是为每个项目设置一个固定高度, Window.Current.Bounds.Height并在窗口高度发生变化时注册Window.Current.SizeChanged以更新它(确保在卸载时取消注册以防止内存泄漏)。
我认为会更复杂的另一种方法是将 VisibilitySwitchControl 的 ItemsPanel 更改为其他内容(默认情况下,它是一个 Stack 面板,因此它会变得比屏幕大),例如更改为您设置的 Grid带有星高的行作为您拥有的项目(然后您需要设置每个项目的行)或通过创建自定义面板。

于 2013-09-23T22:15:28.017 回答
0

您想拉伸列表视图的高度尝试将其绑定到父视图的实际高度

这是您需要包含的代码部分

Height="{Binding ActualHeight, ElementName=parentContainer}"

您正在使用parentContainer的名称在哪里。custom:VisibilitySwitchControl这会将高度绑定到父容器的显示高度。试着让我知道

于 2013-09-24T06:51:02.000 回答