列表框数据模板和可见状态的问题

时间:2011-06-02 19:39:18

标签: silverlight mvvm datatemplate listboxitem

我有一个列表框,其中usercontrol设置为列表框项。在这个列表框中,我有几个网格和两个按钮。

<Grid x:Name="LayoutRoot" HorizontalAlignment="Stretch">
    <Grid.RowDefinitions>
        <RowDefinition Height="120" />
        <RowDefinition x:Name="personDetailHolder" Height="*" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="92.915" />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <StackPanel Grid.RowSpan="2"
                Grid.ColumnSpan="2"
                Margin="0,0,-0.042,0"
                Orientation="Vertical"
                d:LayoutOverrides="Height">
        <Grid Height="117" Margin="3,0,0,0">
            <Grid.RowDefinitions>
                <RowDefinition Height="117" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>
            <Rectangle  />
            <!-- removed for brevity -->

            <Button x:Name="btnViewDetails"
                    Width="106"
                    Height="24"
                    Margin="0,0,3,6"
                    HorizontalAlignment="Right"
                    VerticalAlignment="Bottom"
                    Click="btnDetails_Click"
                    Foreground="#FFFBCE2F"
                    Style="{StaticResource ViewDetailsButton}" />
            <!--  Detail section  -->
            <Grid x:Name="personDetail"
                  Grid.Row="1"
                  MinHeight="365"
                  Margin="0,0,5,-376"
                  VerticalAlignment="Bottom"
                  RenderTransformOrigin="0.5,0.5"
                  Visibility="Collapsed">
                <Rectangle />
                <!--  removed for brevity -->   

                <Button x:Name="btnCloseDetails"
                        Width="123"
                        Height="24"
                        Margin="0,8,8,0"
                        HorizontalAlignment="Right"
                        VerticalAlignment="Top"
                        Click="btnDetails_Click"
                        Foreground="#FFFBC42F"
                        Style="{StaticResource CloseDetailsButton}" />

            </Grid>
        </Grid>
    </StackPanel>
</Grid>

点击事件btnDetails_Click在用户控件

后面的代码中调用一个事件
private void btnDetails_Click(object sender, System.Windows.RoutedEventArgs e)
{
    UIPanelControl cp = new UIPanelControl();
    cp.CheckDetailPanelStatus(this.personDetail, this.personDetailHolder, this.btnViewDetails, this.btnCloseDetails, this.detailAnimation);
}

调用方法

public void CheckDetailPanelStatus(Grid panelName, RowDefinition rowName, Button openButtonName, Button closeButtonName, Storyboard animi)
{
    if (panelName.Visibility == System.Windows.Visibility.Visible)
    {
        panelName.Visibility = System.Windows.Visibility.Collapsed;
        rowName.Height = new GridLength(0);
        openButtonName.Visibility = System.Windows.Visibility.Visible;
        closeButtonName.Visibility = System.Windows.Visibility.Collapsed;
    }
    else
    {
        panelName.Visibility = System.Windows.Visibility.Visible;
        rowName.Height = new GridLength(380);
        openButtonName.Visibility = System.Windows.Visibility.Collapsed;
        closeButtonName.Visibility = System.Windows.Visibility.Visible;
        animi.Begin();

    }
}

此处的目标是向用户返回结果列表。然后,用户可以单击“查看其他详细信息”按钮,展开第二部分,其中显示有关所选记录的更多详细信息。我正在使用MVVM方法,因此命令进入VM以便于第二个记录填充。由于动画,可见性等包含在视图中,我决定将这些事件保留在视图代码中。

此解决方案的部分工作原理是,当我单击按钮时,该部分会针对所选列表框项展开。但是,如果我向下滚动到其他结果,我会发现其他列表框项目间歇性地扩展。这没有可重复的模式(即每5个项目或每隔一个记录)我也看到了如果我选择第一个记录并展开它然后向下滚动到下一个记录并备份第一个记录的实例已重置崩溃了。

我对可能导致此问题的原因感到困惑。

任何人都可以提供有关我为何会看到这种情况或如何防止这种情况发生的任何见解吗?

3 个答案:

答案 0 :(得分:1)

你看到的是列表框使用对象重用来节省内存和提高性能的结果,GridView中也可能发生类似的事情。控件的作用是创建X ListBoxItems并在其数据项超出视图(Loaded / Unloaded)时重用这些容器。因此,如果更改容器的外观,它将更改共享容器的所有数据项的外观。

要解决问题,您也可以; 处理ListBoxItem的Loaded / Unloaded事件并在Unloaded事件触发时修复UI。 或者,将已绑定到列表选择的项目识别出来并让它们更改ListBoxItem外观,因此当它们被加载/卸载时,绑定引擎将负责重置UI。

答案 1 :(得分:0)

而不是使用命令

更改可见性
panelName.Visibility = System.Windows.Visibility.Collapsed;

您希望将xaml中的可见性设置为

    <Grid x:Name="personDetail"
          Grid.Row="1"
          MinHeight="365"
          Margin="0,0,5,-376"
          VerticalAlignment="Bottom"
          RenderTransformOrigin="0.5,0.5"
          Visibility="{Binding PersonDetailVisibility}">

假设您将属性更改事件处理程序连接到以下内容:

        PropertyChanged += new
        PropertyChangedEventHandler(PersonDetailViewModel_PropertyChanged);

然后在更改VM中的PersonDetailVisibility属性后,需要引发属性更改事件

            this.RaisePropertyChanged(() => this.PersonDetailVisibility);

答案 2 :(得分:0)

我认为使用VisualStates可以更好地实现这一点,而不是在click事件上手动设置属性。

只需在列表项的模板中添加两个可视状态,一个用于“ShowDetails”,另一个用于“HideDetails”。然后,您可以使用行为GoToVisualStateBehavior在点击按钮(我认为应该是ToggleButton)之间进行翻转。

否则,您可以使用Expander按钮来实现此目的。

希望这会有所帮助:)