【问题标题】:Binding doesn't work but also doesn't give any errors绑定不起作用,但也没有给出任何错误
【发布时间】:2011-04-05 20:54:50
【问题描述】:

我正在努力让this code(来自博客)工作。

那里没有下载文件,所以我复制了代码片段,它似乎可以工作,除了我必须制作一个绑定但项目没有显示出来。

关于如何解决这个问题的任何想法?听起来我错过了一件微不足道的事情。

<Window x:Class="WpfMultiColumnSorting.SortWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="SortWindow" Height="300" Width="600">
    <ListView Name="DashListView" ItemsSource="{Binding SortedItems}">

        <ListView.View>
            <GridView>
                <GridViewColumn Width="95" DisplayMemberBinding="{Binding Name}">
                    <GridViewColumnHeader Click="SortClick" Tag="Name" Content="Name" />
                </GridViewColumn>

                <GridViewColumn Width="90">
                    <GridViewColumnHeader Click="SortClick" Tag="IsActive" Content="Activitation" />
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal" ToolTip="{Binding IsActive}">
                                <TextBlock Name="ActivityStatusText" Text="{Binding IsActive}"></TextBlock>
                            </StackPanel>
                            <DataTemplate.Triggers>
                                <DataTrigger Binding="{Binding IsActive}" Value="true">
                                    <Setter TargetName="ActivityStatusText" Property="FontWeight" Value="Bold" />
                                </DataTrigger>
                            </DataTemplate.Triggers>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>

                <GridViewColumn Width="140" DisplayMemberBinding="{Binding CreationDate}">
                    <GridViewColumnHeader Click="SortClick" Tag="CreationDate" Content="Created On" />
                </GridViewColumn>

                <GridViewColumn Width="85" DisplayMemberBinding="{Binding Value}">
                    <GridViewColumnHeader Click="SortClick" Tag="Value" Content="Value #" />
                </GridViewColumn>
            </GridView>
        </ListView.View>
    </ListView>
</Window>





using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Globalization;
using System.Collections.ObjectModel;

namespace WpfMultiColumnSorting
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>

    public partial class SortWindow : Window
    {
        ObservableCollection<SortedItemViewModel> sortedItems;
        public ObservableCollection<SortedItemViewModel> SortedItems
        {
            get { return this.sortedItems; }
            set
            {
                this.sortedItems = value;
                this.RaisePropertyChanged ( "SortedItems" );
            }
        }

        public SortWindow ( )
        {
            this.SortedItems = new ObservableCollection<SortedItemViewModel> ( );

            this.SortedItems = new ObservableCollection<SortedItemViewModel> ( ) {
                new SortedItemViewModel ( "A", false, DateTime.Now, "1" ),
                new SortedItemViewModel ( "B", false, DateTime.Now, "2" ),
                new SortedItemViewModel ( "C", false, DateTime.Now, "3" ),
                new SortedItemViewModel ( "D", false, DateTime.Now, "4" ),
                new SortedItemViewModel ( "E", false, DateTime.Now, "5" ),
                new SortedItemViewModel ( "F", false, DateTime.Now, "6" ),
                new SortedItemViewModel ( "G", false, DateTime.Now, "7" )
            };
        }

        #region Events

        public event PropertyChangedEventHandler PropertyChanged;
        void RaisePropertyChanged ( string propertyName )
        {
            var handler = this.PropertyChanged;
            if ( handler != null )
                handler ( this, new PropertyChangedEventArgs ( propertyName ) );
        }

        #endregion

        private List<GridViewColumnHeader> _sortColumnStack = new List<GridViewColumnHeader> ( );

        private IDictionary<GridViewColumnHeader, SortAdorner> _adorners = new Dictionary<GridViewColumnHeader, SortAdorner> ( );


        private void SortClick ( object sender, RoutedEventArgs e )
        {
            GridViewColumnHeader column = sender as GridViewColumnHeader;
            ListSortDirection newDir = ListSortDirection.Ascending;

            // Control means clear out all the prior sort stack
            bool clear = Keyboard.Modifiers == ModifierKeys.Control;

            PerformSort ( column, newDir, clear );
        }


        /// <summary>
        /// Updates the sort stack
        /// </summary>
        /// <param name="column">The columkn on which we are sorting</param>
        /// <param name="newDir">The direction we should place the column sort into</param>
        /// <param name="clear">true to clear out all curent sorting</param>
        private void PerformSort ( GridViewColumnHeader column, ListSortDirection newDir, bool clear )
        {
            IDictionary<GridViewColumnHeader, SortAdorner> oldAdorners = new Dictionary<GridViewColumnHeader, SortAdorner> ( );

            // determine if we are clicking an already sorted column
            if ( _sortColumnStack.Contains ( column ) && _adorners.ContainsKey ( column ) )
            {
                if ( _sortColumnStack [ _sortColumnStack.Count - 1 ] != column )
                {
                    // if it is not the primary use the same direction
                    newDir = _adorners [ column ].Direction;
                }
                else
                {
                    // if it is the primary column then flip it
                    if ( newDir == _adorners [ column ].Direction )
                        newDir = ListSortDirection.Descending;
                }
            }

            // remove all the adorners so we can start a fresh
            foreach ( GridViewColumnHeader col in _adorners.Keys )
            {
                // save into our old adorners list
                oldAdorners [ col ] = _adorners [ col ];
                // then remove it
                AdornerLayer.GetAdornerLayer ( col ).Remove ( _adorners [ col ] );
            }
            _adorners.Clear ( );

            // get rid of all the sorting
            DashListView.Items.SortDescriptions.Clear ( );

            // Control means clear out all the prior sort stack
            if ( clear )
            {
                _sortColumnStack.Clear ( );
            }
            else
            {
                // remove ourselves from the stack if we are in it
                if ( _sortColumnStack.Contains ( column ) )
                {
                    _sortColumnStack.Remove ( column );
                }
            }

            // add our brand new primary one
            _sortColumnStack.Add ( column );

            // now re-create the adorners from our stack
            for ( int i = _sortColumnStack.Count - 1; i >= 0; i-- )
            {
                GridViewColumnHeader col = _sortColumnStack [ i ];
                SortAdorner adorner;

                if ( i == _sortColumnStack.Count - 1 )
                {
                    // create a new one (for the last one)
                    adorner = new SortAdorner ( col, newDir, col.Tag as string, _sortColumnStack.Count - i );
                }
                else if ( oldAdorners.ContainsKey ( col ) )
                {
                    // re-use the old adorner information
                    SortAdorner oldAdorner = oldAdorners [ col ];
                    adorner = new SortAdorner ( col, oldAdorner.Direction, col.Tag as string, _sortColumnStack.Count - i );
                }
                else
                {
                    // create a new one (for the last one)
                    adorner = new SortAdorner ( col, newDir, col.Tag as string, _sortColumnStack.Count - i );
                }

                _adorners.Add ( col, adorner );
                AdornerLayer.GetAdornerLayer ( col ).Add ( _adorners [ col ] );
                DashListView.Items.SortDescriptions.Add ( new SortDescription (
                _adorners [ col ].Field, _adorners [ col ].Direction ) );
            }
        }
    }
}





using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

namespace WpfMultiColumnSorting
{
    public class SortedItemViewModel : INotifyPropertyChanged
    {
        string name;
        public string Name
        {
            get { return name; }
            set
            {
                this.name = value;
                this.RaisePropertyChanged ( "Name" );
            }
        }

        public bool IsActive { get; set; }
        public DateTime CreationDate { get; set; }
        public string Value { get; set; }

        public SortedItemViewModel ( string name, bool isActive, DateTime creationDate, string value )
        {
            this.Name = name;
            this.IsActive = isActive;
            this.CreationDate = creationDate;
            this.Value = value;
        }

        #region Events

        public event PropertyChangedEventHandler PropertyChanged;
        void RaisePropertyChanged ( string propertyName )
        {
            var handler = this.PropertyChanged;
            if ( handler != null )
                handler ( this, new PropertyChangedEventArgs ( propertyName ) );
        }

        #endregion
    }
}




using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Documents;
using System.Windows.Media;
using System.ComponentModel;
using System.Windows;
using System.Globalization;

namespace WpfMultiColumnSorting
{
    public class SortAdorner : Adorner
    {
        private readonly static Geometry AscGeometry = Geometry.Parse ( "M 0,0 L 8,0 L 4,5 Z" );

        private readonly static Geometry DescGeometry = Geometry.Parse ( "M 0,5 L 8,5 L 4,0 Z" );

        public ListSortDirection Direction { get; private set; }

        public string Field { get; private set; }

        public int SortOrder { get; private set; }

        public SortAdorner ( UIElement element, ListSortDirection dir, string field, int order )
            : base ( element )
        {
            Direction = dir;
            Field = field;
            SortOrder = order;
        }

        protected override void OnRender ( DrawingContext drawingContext )
        {
            base.OnRender ( drawingContext );

            if ( AdornedElement.RenderSize.Width < 20 )
                return;

            drawingContext.PushTransform ( new TranslateTransform (
            AdornedElement.RenderSize.Width - 15, ( AdornedElement.RenderSize.Height - 5 ) / 2 ) );

            drawingContext.DrawGeometry ( SortOrder == 1 ? Brushes.Black : Brushes.DarkGray, null,
            Direction == ListSortDirection.Ascending ? AscGeometry : DescGeometry );

            // annotate each arrow adorner with a number if it is not the first one
            if ( SortOrder != 1 )
            {
                drawingContext.DrawText ( new FormattedText (
                SortOrder.ToString ( ), CultureInfo.GetCultureInfo ( "en-us" ),
                FlowDirection.LeftToRight, new Typeface ( "Verdana" ), 9,
                Brushes.Black ), new Point ( 7, 0 ) );
            }

            drawingContext.Pop ( );
        }
    }
}

没有编译错误或运行时错误,并且列表视图为空。

【问题讨论】:

  • 仔细检查输出窗口。绑定错误几乎无声无息地失败 - 但它们应该输出一些信息来表明它们已经失败。
  • 我检查过了,但没有打印绑定表达式失败错误,通常我以前在其他项目中见过很多次。

标签: c# .net wpf sorting binding


【解决方案1】:

您似乎没有为 ListView 设置 DataContext。创建一个名为 SortWindowViewModel 的新类,并将 SortWindow.xaml.cs 中的大部分代码移至这个新类。在 SortWindow.xaml.cs 中添加 Loaded 事件处理程序并添加 DataContext = new SortWindowViewModel(); 绑定看起来不错,只是缺少这些绑定指向的位置。

【讨论】:

  • 我在 Window 中添加了这个到 xaml:DataContext="{Binding RelativeSource={RelativeSource Self}}" 并且成功了,非常感谢。
  • 很高兴我能帮上忙。如果你正在关注 MVVM,那么你应该创建一个新的视图模型类,但如果你只是用它来玩,那没关系。
  • 谢谢,我会按照您的描述进行操作,但没有完全理解。我正在使用 MVVM,但我认为使用 SortedItemViewModel 进行此操作使其成为 MVVM 风格。那我想不会吧?
  • SortedItemViewModel 看起来很合适,但您不应该将 DataContext 指向自身,因此我建议创建一个名为 SortWindowViewModel 的新类并将构造函数中的 sortedItems 和代码移出 SortWindow.xaml.cs到新的视图模型类。在 SortWindow.xaml.cs 的构造函数中添加DataContext = new SortWindowViewModel();
【解决方案2】:

我不时在 WPF 中看到过这种情况。我不知道为什么会发生这种情况,但通常可以通过将数据模板移出控制并进入资源部分并按名称或类型引用它们来解决。

【讨论】:

    猜你喜欢
    • 2011-02-10
    • 1970-01-01
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 2020-04-08
    • 1970-01-01
    • 1970-01-01
    • 2018-07-25
    相关资源
    最近更新 更多