开发者

How to prevent ListView from Cutting off Items

I'm using a ListView box that is extending a custom property, ListViewcolumns.Stretch. This is so I can have 3 columns that space themselves evenly regardless of Window size. My problem is at the end of the listview items are being "cut off"

So my listview contains 3 columns, Red, Green, and Black, when I insert an item it inserts into the appropriate column and the other two columns inserts blank text. It inserts the items at the 0 location so it always shows on top and pushes everything else down. The scrollbar is by default off.

-- Goal is to have 3 columns take up the entire window space regardless of how big or small the window is and resize the text appropriately (max height around 100-150). AND then when rows fill up the entire collection the bottom row cannot "span" out of view, it should either be all in view or none in view.

Anyways - the codes. Any help would be appreciated, I could hard code the maxheight of the viewbox until I found the perfect size that works on my target monitor but ideally I want it to resize appropriately

ListView

<ListView Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="Transparent" Margin="15,10,5,5"
                      FontFamily="Impact" FontWeight="Bold" BorderThickness="0" VerticalContentAlignment="Stretch"
                  ScrollViewer.VerticalScrollBarVisibility="{Binding VerticleScrollVisibility}" ScrollViewer.HorizontalScrollBarVisibility="Auto"
                  ItemsSource="{Binding PlayNumbers}"
                  ItemContainerStyle="{StaticResource ListViewStyle}" ext:ListViewColumns.Stretch="True">
                <ListView.View>
                    <GridView>
                        <GridView.ColumnHeaderContainerStyle>
                            <Style>
                                <Setter Property="FrameworkElement.Visibility" Value="Collapsed" />
                            </Style>
                        </GridView.ColumnHeaderContainerStyle>
                        <GridView.Columns>
                        <GridViewColumn Header="Red" CellTemplate="{StaticResource RedItemTemplate}" />
                            <GridViewColumn Header="Green" CellTemplate="{StaticResource GreenItemTemplate}" />
                            <GridViewColumn Header="Black" CellTemplate="{StaticResource BlackItemTemplate}" />
                        </GridView.Columns>
                    </GridView>
                </ListView.View>
    </ListView>

Skin File

    <!--        Templates for Number ListBox            -->
<DataTemplate x:Key="RedItemTemplate">
    <Viewbox MaxHeight="140" VerticalAlignment="Stretch">
        <TextBlock Text="{Binding Path=RedItem}" HorizontalAlignment="Center" Foreground="Red" />
    </Viewbox>
</DataTemplate>

<DataTemplate x:Key="GreenItemTemplate">
    <Viewbox MaxHeight="140" VerticalAlignment="Stretch">
        <TextBlock Text="{Binding Path=GreenItem}" HorizontalAlignment="Center" Foreground="Green" />
    </Viewbox>
</DataTemplate>

<DataTemplate x:Key="BlackItemTemplate">
    <Viewbox MaxHeight="140" VerticalAlignment="Stretch">
        <TextBlock Text="{Binding Path=BlackItem}" HorizontalAlignment="Center" Foreground="LightGray" />
    </Viewbox>
</DataTemplate>

<Style x:Key="ListViewStyle" TargetType="{x:Type ListViewItem}">
    <Setter Property="Background" Value="Transparent" />
    <Setter Property="HorizontalContentAlignment" Value="Stretch" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ListViewItem}">
                <Border x:Name="Bd" Background="{TemplateBinding Background}"
                        SnapsToDevicePixels="True" BorderThickness="0,0,0,1" BorderBrush="Transparent">
                    <GridViewRowPresenter VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsSelected" Value="false" />
                    <Trigger Property="IsMouseOver" Value="false" />
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Custom Property

    /// <summary>
/// ListViewColumnStretch
/// </summary>
public class ListViewColumns : DependencyObject
{

    #region Fields

    /// <summary>
    /// Holds a reference to our parent ListView control
    /// </summary>
    private ListView _parentListView = null;

    #endregion

    #region Dependency Property Infrastructure

    /// <summary>
    /// IsStretched Dependency property which can be attached to gridview columns.
    /// </summary>
    public static readonly DependencyProperty StretchProperty =
        DependencyProperty.RegisterAttached("Stretch",
        typeof(bool),
        typeof(ListViewColumns),
        new UIPropertyMetadata(true, null, OnCoerceStretch));


    /// <summary>
    /// Gets the stretch.
    /// </summary>
    /// <param name="obj">The obj.</param>
    /// <returns></returns>
    public static bool GetStretch(DependencyObject obj)
    {
        return (bool)obj.GetValue(StretchProperty);
    }

    /// <summary>
    /// Sets the stretch.
    /// </summary>
    /// <param name="obj">The obj.</param>
    /// <param name="value">if set to <c>true</c> [value].</param>
    public static void SetStretch(DependencyObject obj, bool value)
    {
        obj.SetValue(StretchProperty, value);
    }

    /// <summary>
    /// Called when [coerce stretch].
    /// </summary>
    /// <remarks>If this callback seems unfamilar then please read
    /// the great blog post by Paul jackson found here. 
    /// http://compilewith.net/2007/08/wpf-dependency-properties.html</remarks>
    /// <param name="source">The source.</param>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    public static object OnCoerceStretch(DependencyObject source, object value)
    {
        ListView lv = (source as ListView);

        //Ensure we dont have an invalid dependency object of type ListView.
        if (lv == null)
            throw new ArgumentException("This property may only be used on ListViews");

        //Setup our event handlers for this list view.
        lv.Loaded += new RoutedEventHandler(lv_Loaded);
        lv.SizeChanged += new SizeChangedEventHandler(lv_SizeChanged);
        return value;
    }

    #endregion

    #region Event Handlers

    /// <summary>
    /// Handles the SizeChanged event of the lv control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.Windows.SizeChangedEventArgs"/> instance containing the event data.</param>
    private static void lv_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        ListView lv = (sender as ListView);
        if (lv.IsLoaded)
        {
            //Set our initial widths.
            SetColumnWidths(lv);
        }
    }

    /// <summary>
    /// Handles the Loaded event of the lv control.
    /// </summary>
    /// <param name="sender">The source of the event.</param>
    /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
    private static void lv_Loaded(object sender, RoutedEventArgs e)
    {
        ListView lv = (sender as ListView);
        //Set our initial widths.
        SetColumnWidths(lv);
    }
    #endregion

    #region Private Members

    /// <summary>
    /// Sets the column widths.
    /// </summary>
    private static void Set开发者_C百科ColumnWidths(ListView listView)
    {
        //Pull the stretch columns fromt the tag property.
        List<GridViewColumn> columns = (listView.Tag as List<GridViewColumn>);
        double specifiedWidth = 0;
        GridView gridView = listView.View as GridView;
        if (gridView != null)
        {
            if (columns == null)
            {
                //Instance if its our first run.
                columns = new List<GridViewColumn>();
                // Get all columns with no width having been set.
                foreach (GridViewColumn column in gridView.Columns)
                {
                    if (!(column.Width >= 0))
                        columns.Add(column);
                    else specifiedWidth += column.ActualWidth;
                }
            }
            else
            {
                // Get all columns with no width having been set.
                foreach (GridViewColumn column in gridView.Columns)
                    if (!columns.Contains(column))
                        specifiedWidth += column.ActualWidth;
            }

            // Allocate remaining space equally.
            foreach (GridViewColumn column in columns)
            {
                double newWidth = (listView.ActualWidth - specifiedWidth) / columns.Count;
                if (newWidth >= 0) column.Width = newWidth - 10;
            }

            //Store the columns in the TAG property for later use. 
            listView.Tag = columns;
        }
    }


    #endregion

}


I know this is an old question, but here is another solution for anyone else. On the style for the ListViewItem, also set HorizontalAlignment to Stretch and With to Auto.

    <!--ListViewItem-->
    <Style TargetType="ListViewItem" x:Key="ListViewItemStyle">
        <Setter Property="HorizontalContentAlignment" Value="Stretch" />
        <Setter Property="HorizontalAlignment" Value="Stretch" />
        <Setter Property="Width" Value="Auto" />
    </Style>


This is a bit indirect, but when faced with limitations of one control, why not try a different approach? Instead of using ListView's GridView, try using the DataGrid, it allows for proportional column growth. I am just going to post a stripped down version from your' XAML, but you'll get the point (which is Width="33*")

<DataGrid>
    <DataGrid.Columns>
        <DataGridTextColumn Header="Red" Width="33*"/>
        <DataGridTextColumn Header="Green" Width="33*"/>
        <DataGridTextColumn Header="Black" Width="33*"/>
     </DataGrid.Columns>
</DataGrid>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜