【WPF】ListView绑定自定义的ObservableDictionary,绑定 DataTemplate内的控件时候,命令会失效

自定义类ObservableDictionary

注意:

(1)绑定字典时候要用Value.字段例如: Text="{Binding Value.Close, StringFormat={}{0:F2}}">, StringFormat={}{0:F2}是格式化字段,格式化字段请看WPF编程宝典20章

StringFormat, 当格式化字符位于开始时, 比如StringFormat={0:C}这样子的话, 必须前缀加上{}, 不然显示失败。原因是不让系统误认为是标记扩展。 正确的结果就是StringFormat={}{0:C}


复制代码
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Spider.Comment
{

    using System;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.ComponentModel;
    using System.Runtime.CompilerServices;

    namespace ObservableDictionary
    {
        public delegate void NotifyDictionaryChangedEventHandler(object sender, NotifyDictionaryChangedEventArgs e);
        public class NotifyDictionaryChangedEventArgs
        {
            public NotifyCollectionChangedAction Action { get; }
            public object AddedKey { get; }
            public object AddedItem { get; }
            public object RemovedKey { get; }
            public object RemovedItem { get; }

            public NotifyDictionaryChangedEventArgs(NotifyCollectionChangedAction action)
            {
                this.Action = action;
            }
            public NotifyDictionaryChangedEventArgs(NotifyCollectionChangedAction action, object changedItem, object key)
            {
                this.Action = action;
                this.AddedItem = changedItem;
                this.AddedKey = key;
            }
            public NotifyDictionaryChangedEventArgs(NotifyCollectionChangedAction action, object addedItem, object addedKey, object removedItem, object removedKey)
            {
                this.Action = action;
                this.AddedItem = addedItem;
                this.AddedKey = addedKey;
                this.RemovedItem = removedItem;
                this.RemovedKey = removedKey;
            }
        }
        public interface INotifyDictionaryChanged
        {
            event NotifyDictionaryChangedEventHandler DictionaryChanged;
        }
        public interface IObservableMap<TValue> : IEnumerable<KeyValuePair<string, TValue>>, INotifyDictionaryChanged
        {
            TValue this[string key] { get; set; }
            bool ContainsKey(string key);
            void Remove(string key);
            void Add(string key, TValue value);
        }
        public class ObservableStringDictionary<TValue> : Dictionary<string, TValue>, IObservableMap<TValue>, INotifyDictionaryChanged, INotifyPropertyChanged
        {
            #region public
            public new TValue this[string key]
            {
                get => base[key];
                set
                {
                    base[key] = value;
                    this.OnPropertyChanged(CountString);
                    this.OnPropertyChanged(IndexerNameBeg + IndexerNameEnd);
                    this.OnPropertyChanged(IndexerNameBeg + key + IndexerNameEnd);
                    this.OnCollectionChanged(NotifyCollectionChangedAction.Reset, key, value);
                }
            }

            public new void Add(string key, TValue value)
            {
                base.Add(key, value);
                this.OnPropertyChanged(CountString);
                this.OnPropertyChanged(IndexerNameBeg + IndexerNameEnd);
                this.OnPropertyChanged(IndexerNameBeg + key + IndexerNameEnd);
                this.OnCollectionChanged(NotifyCollectionChangedAction.Add, key, value);
            }
            public new void Clear()
            {
                base.Clear();
                this.OnPropertyChanged(CountString);
                this.OnPropertyChanged(IndexerNameBeg + IndexerNameEnd);
                this.OnCollectionReset();
            }
            public new void Remove(string key)
            {
                TValue removedItem = this[key];
                base.Remove(key);
                this.OnPropertyChanged(CountString);
                this.OnPropertyChanged(IndexerNameBeg + IndexerNameEnd);
                this.OnPropertyChanged(IndexerNameBeg + key + IndexerNameEnd);
                this.OnCollectionChanged(NotifyCollectionChangedAction.Remove, key, removedItem);
            }
            event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
            {
                add => this.PropertyChanged += value;
                remove => this.PropertyChanged -= value;
            }
#if !FEATURE_NETCORE
            [field: NonSerializedAttribute()]
#endif
            public virtual event NotifyDictionaryChangedEventHandler DictionaryChanged;

#if !FEATURE_NETCORE
            [field: NonSerializedAttribute()]
#endif
            protected virtual event PropertyChangedEventHandler PropertyChanged;

            private void OnCollectionChanged(NotifyCollectionChangedAction action, string key, TValue value)
            {
                this.OnCollectionChanged(new NotifyDictionaryChangedEventArgs(action, value, key));
            }
            protected virtual void OnCollectionChanged(NotifyDictionaryChangedEventArgs e)
            {
                if (this.DictionaryChanged is null) return;
                using (this.BlockReentrancy())
                {
                    this.DictionaryChanged(this, e);
                }
            }
            protected IDisposable BlockReentrancy()
            {
                this._monitor.Enter();
                return this._monitor;
            }
            protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
            {
                this.PropertyChanged?.Invoke(this, e);
            }

            #endregion
            #region private
            private void OnPropertyChanged(string propertyName)
            {
                this.OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
            }
            private void OnCollectionReset()
            {
                this.OnCollectionChanged(new NotifyDictionaryChangedEventArgs(NotifyCollectionChangedAction.Reset));
            }
            #endregion Private Methods
            #region Private Types

            // this class helps prevent reentrant calls
#if !FEATURE_NETCORE
            [Serializable()]
            [TypeForwardedFrom("WindowsBase, Version=3.0.0.0, Culture=Neutral, PublicKeyToken=31bf3856ad364e35")]
#endif
            private class SimpleMonitor : IDisposable
            {
                public void Enter()
                {
                    ++this._busyCount;
                }

                public void Dispose()
                {
                    --this._busyCount;
                }

                public bool Busy { get => this._busyCount > 0; }

                int _busyCount;
            }

            #endregion Private Types
            #region Private Fields

            private const string CountString = "Count";

            // This must agree with Binding.IndexerName.  It is declared separately
            // here so as to avoid a dependency on PresentationFramework.dll.
            private const string IndexerNameBeg = "Item[";
            private const string IndexerNameEnd = "]";

            private SimpleMonitor _monitor = new SimpleMonitor();

            #endregion Private Fields
        }
    }

}
复制代码

 

绑定ListView,

注意 GridViewColumn 用了 DisplayMemberBinding  ,使得CellTemplate失效。 两者的这能选一个,DisplayMemberBinding  权重大于CellTemplate

(1)绑定<DataTemplate>内的控件时候,命令会失效,要把命令直接绑定到 元数据所绑定的控件的DataContext上

一定要这样写Command="{Binding DataContext.AddSelfselectionStockCommand, ElementName=dashboard ,Mode=TwoWay}"

(2)、<DataTemplate>标签内的命令 ,要使用路由命令或者自定义命令连接到命令管理器如下:

    public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

 

复制代码
                          <ListView ItemContainerStyle="{DynamicResource ListViewItemContainerStyle}" 
                                      ItemsSource="{Binding AllBoardStocksData}" 
                                       VirtualizingPanel.VirtualizationMode="Recycling"
                                       VirtualizingPanel.IsVirtualizing="True" 
                                       Background="Transparent"
                                        BorderThickness="0"   >

                                <ListView.View >
                                    <GridView   ColumnHeaderContainerStyle="{DynamicResource ColumnHeaderContainerStyle}"    >

                                        <GridViewColumn  Width="100">
                                            <GridViewColumnHeader Style="{DynamicResource HeaderGridViewColumnHeaderStyle}"  Cursor="Hand"   Content="代码"     />
                                            <GridViewColumn.CellTemplate  >
                                                <DataTemplate >
                                                    <TextBlock Margin="10" Background="Gray" Text="{Binding Value.Code}"></TextBlock>
                                                </DataTemplate>
                                            </GridViewColumn.CellTemplate>
                                        </GridViewColumn>

                                        <GridViewColumn  Header="名称"     DisplayMemberBinding="{Binding Value.Name }" />

                                        <GridViewColumn Header="现价">
                                            <GridViewColumn.CellTemplate>
                                                <DataTemplate>
                                                    <TextBlock    x:Name="CloseTextBoxStyle"  Text="{Binding Value.Close, StringFormat={}{0:F2}}"></TextBlock>
                                                    <DataTemplate.Triggers>
                                                        <DataTrigger   Binding="{Binding Value.Chg_rate, Converter={StaticResource IntToboolConverter}}" Value="true">
                                                            <Setter TargetName="CloseTextBoxStyle" Property="Foreground" Value="red"/>
                                                        </DataTrigger>
                                                        <DataTrigger  Binding="{Binding Value.Chg_rate, Converter={StaticResource IntToboolConverter}}" Value="false">
                                                            <Setter TargetName="CloseTextBoxStyle" Property="Foreground" Value=" green"/>
                                                        </DataTrigger>


                                                    </DataTemplate.Triggers>
                                                </DataTemplate>
                                            </GridViewColumn.CellTemplate>
                                        </GridViewColumn>
                                        <GridViewColumn Header="涨跌幅">
                                            <GridViewColumn.CellTemplate>
                                                <DataTemplate>
                                                    <TextBlock    x:Name="UpDowpTextBoxStyle"  Text="{Binding StringFormat={}{0}%,Path= Value.Chg_rate}"></TextBlock>
                                                    <DataTemplate.Triggers>
                                                        <DataTrigger  Binding="{Binding Value.Chg_rate, Converter={StaticResource IntToboolConverter}}" Value="true">
                                                            <Setter TargetName="UpDowpTextBoxStyle" Property="Foreground" Value="red"/>
                                                         </DataTrigger>
                                                        <DataTrigger  Binding="{Binding Value.Chg_rate, Converter={StaticResource IntToboolConverter}}" Value="false">
                                                            <Setter TargetName="UpDowpTextBoxStyle" Property="Foreground" Value=" green"/>
                                                        </DataTrigger>


                                                    </DataTemplate.Triggers>
                                                </DataTemplate>
                                            </GridViewColumn.CellTemplate>
                                        </GridViewColumn>
                                        <GridViewColumn Header="总市值(亿)"    DisplayMemberBinding="{Binding Value.TotalValue,StringFormat=000.000E+0010}"  />
                                        <GridViewColumn   Header="加入自选股">
                                            <GridViewColumn.CellTemplate>
                                                <DataTemplate>
                                                    <CheckBox Name="isselectstock" IsThreeState="False" IsChecked="{Binding Value.IsSelfselectionStock }" Command="{Binding DataContext.AddSelfselectionStockCommand, ElementName=dashboard ,Mode=TwoWay}" >
                                                        <CheckBox.CommandParameter>
                                                            <MultiBinding Converter="{StaticResource CodeAndCheckboxStateMultiConverter}">
                                                                <Binding Path="IsChecked" ElementName="isselectstock"/>
                                                                <Binding Path="Value.Code"  />
                                                            </MultiBinding>
                                                        </CheckBox.CommandParameter>
                                                     
                                                    </CheckBox>
                                                </DataTemplate>
                                            </GridViewColumn.CellTemplate>
                                            
                                        </GridViewColumn>
                                        <GridViewColumn Header="详情">
                                            <GridViewColumn.CellTemplate>
                                                <DataTemplate>
                                                    <Button >详情</Button>
                                                </DataTemplate>
                                            </GridViewColumn.CellTemplate>

                                        </GridViewColumn>
                                    </GridView>
                                </ListView.View>
                            </ListView>
复制代码

 3、Listview 绑定复杂的对象,并且显示复杂的对象。

 

 此时代码中不能用DisplayMemberBinding  ,而要用CellTemplate 。在该案例CellTemplate的数据上下文是LinePoco,所以模板中要具体到列(属性)中就是ALine等,该属性对应是类型是PhonogramPoco

 

复制代码
   public class PhonogramPoco
    {
        /// <summary>
        /// 平假名
        /// </summary>
        public string? Hiragana { get; set; }
        /// <summary>
        /// 片假名
        /// </summary>
        public string? Katakana { get; set; }
        /// <summary>
        /// 音标
        /// </summary>
        public string? Soundmark { get; set; }

        /// <summary>
        /// 读音
        /// </summary>
        public string? SoundUri { get; set; }
    }

  public  class linePoco
    {
        public PhonogramPoco? ALine { set; get; }=null;     
        public PhonogramPoco? ILine { set; get; }=null;     
        public PhonogramPoco? ULine { set; get; }=null;     
        public PhonogramPoco? ELine { set; get; }=null;     
        public PhonogramPoco? OLine { set; get; }=null;     
             
         
    }
复制代码

 

posted @   小林野夫  阅读(659)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
历史上的今天:
2021-09-24 自定义表链 SnakList
原文链接:https://www.cnblogs.com/cdaniu/
点击右上角即可分享
微信分享提示