坚强的老罗 發表於 2025-4-30 10:45:00

WPF封装一个懒加载下拉列表控件(支持搜索)

<div>因为项目中PC端前端针对基础数据选择时的下拉列表做了懒加载控件,PC端使用现成的组件,为保持两端的选择方式统一,WPF客户端上也需要使用懒加载的下拉选择。</div>
<div>WPF这种懒加载的控件未找到现成可用的组件,于是自己封装了一个懒加载和支持模糊过滤的下拉列表控件,控件使用了虚拟化加载,解决了大数据量时的渲染数据卡顿问题,下面是完整的代码和示例:</div>
<div>&nbsp;</div>
<div>
<div>一、控件所需的关键实体类</div>
<div>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)"> 2</span> <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 下拉项
</span><span style="color: rgba(0, 128, 128, 1)"> 3</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)"> 4</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> ComboItem
</span><span style="color: rgba(0, 128, 128, 1)"> 5</span> <span style="color: rgba(0, 0, 0, 1)">{
</span><span style="color: rgba(0, 128, 128, 1)"> 6</span>   <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)"> 7</span>   <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 实际存储值
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span>   <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)"> 9</span>   <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">string</span>? ItemValue { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
</span><span style="color: rgba(0, 128, 128, 1)">10</span>   <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">11</span>   <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 显示文本
</span><span style="color: rgba(0, 128, 128, 1)">12</span>   <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">13</span>   <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">string</span>? ItemText { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
</span><span style="color: rgba(0, 128, 128, 1)">14</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">15</span>
<span style="color: rgba(0, 128, 128, 1)">16</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">17</span> <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 懒加载下拉数据源提供器
</span><span style="color: rgba(0, 128, 128, 1)">18</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">19</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> ComboItemProvider : ILazyDataProvider&lt;ComboItem&gt;
<span style="color: rgba(0, 128, 128, 1)">20</span> <span style="color: rgba(0, 0, 0, 1)">{
</span><span style="color: rgba(0, 128, 128, 1)">21</span>   <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">readonly</span> List&lt;ComboItem&gt;<span style="color: rgba(0, 0, 0, 1)"> _all;
</span><span style="color: rgba(0, 128, 128, 1)">22</span>   <span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> ComboItemProvider()
</span><span style="color: rgba(0, 128, 128, 1)">23</span> <span style="color: rgba(0, 0, 0, 1)">    {
</span><span style="color: rgba(0, 128, 128, 1)">24</span>         _all = Enumerable.Range(<span style="color: rgba(128, 0, 128, 1)">1</span>, <span style="color: rgba(128, 0, 128, 1)">1000000</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">25</span>                        .Select(i =&gt; <span style="color: rgba(0, 0, 255, 1)">new</span> ComboItem { ItemValue = i.ToString(), ItemText = $<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Item {i}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)"> })
</span><span style="color: rgba(0, 128, 128, 1)">26</span> <span style="color: rgba(0, 0, 0, 1)">                         .ToList();
</span><span style="color: rgba(0, 128, 128, 1)">27</span> <span style="color: rgba(0, 0, 0, 1)">    }
</span><span style="color: rgba(0, 128, 128, 1)">28</span>   <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">async</span> Task&lt;PageResult&lt;ComboItem&gt;&gt; FetchAsync(<span style="color: rgba(0, 0, 255, 1)">string</span> filter, <span style="color: rgba(0, 0, 255, 1)">int</span> pageIndex, <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> pageSize)
</span><span style="color: rgba(0, 128, 128, 1)">29</span> <span style="color: rgba(0, 0, 0, 1)">    {
</span><span style="color: rgba(0, 128, 128, 1)">30</span>         <span style="color: rgba(0, 0, 255, 1)">await</span> Task.Delay(<span style="color: rgba(128, 0, 128, 1)">100</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">31</span>         <span style="color: rgba(0, 0, 255, 1)">var</span> q =<span style="color: rgba(0, 0, 0, 1)"> _all.AsQueryable();
</span><span style="color: rgba(0, 128, 128, 1)">32</span>         <span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">.IsNullOrEmpty(filter))
</span><span style="color: rgba(0, 128, 128, 1)">33</span>             q = q.Where(x =&gt;<span style="color: rgba(0, 0, 0, 1)"> x.ItemText.Contains(filter, StringComparison.OrdinalIgnoreCase));
</span><span style="color: rgba(0, 128, 128, 1)">34</span>         <span style="color: rgba(0, 0, 255, 1)">var</span> page = q.Skip(pageIndex *<span style="color: rgba(0, 0, 0, 1)"> pageSize).Take(pageSize).ToList();
</span><span style="color: rgba(0, 128, 128, 1)">35</span>         <span style="color: rgba(0, 0, 255, 1)">bool</span> has = q.Count() &gt; (pageIndex + <span style="color: rgba(128, 0, 128, 1)">1</span>) *<span style="color: rgba(0, 0, 0, 1)"> pageSize;
</span><span style="color: rgba(0, 128, 128, 1)">36</span>         <span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> PageResult&lt;ComboItem&gt; { Items = page, HasMore =<span style="color: rgba(0, 0, 0, 1)"> has };
</span><span style="color: rgba(0, 128, 128, 1)">37</span> <span style="color: rgba(0, 0, 0, 1)">    }
</span><span style="color: rgba(0, 128, 128, 1)">38</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">39</span>
<span style="color: rgba(0, 128, 128, 1)">40</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">41</span> <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 封装获取数据的接口
</span><span style="color: rgba(0, 128, 128, 1)">42</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">43</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;typeparam name="T"&gt;&lt;/typeparam&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">44</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">interface</span> ILazyDataProvider&lt;T&gt;
<span style="color: rgba(0, 128, 128, 1)">45</span> <span style="color: rgba(0, 0, 0, 1)">{
</span><span style="color: rgba(0, 128, 128, 1)">46</span>   Task&lt;PageResult&lt;T&gt;&gt; FetchAsync(<span style="color: rgba(0, 0, 255, 1)">string</span> filter, <span style="color: rgba(0, 0, 255, 1)">int</span> pageIndex, <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> pageSize);
</span><span style="color: rgba(0, 128, 128, 1)">47</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">48</span>
<span style="color: rgba(0, 128, 128, 1)">49</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">50</span> <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 懒加载下拉分页对象
</span><span style="color: rgba(0, 128, 128, 1)">51</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">52</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;typeparam name="T"&gt;&lt;/typeparam&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">53</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span> PageResult&lt;T&gt;
<span style="color: rgba(0, 128, 128, 1)">54</span> <span style="color: rgba(0, 0, 0, 1)">{
</span><span style="color: rgba(0, 128, 128, 1)">55</span>   <span style="color: rgba(0, 0, 255, 1)">public</span> IReadOnlyList&lt;T&gt; Items { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
</span><span style="color: rgba(0, 128, 128, 1)">56</span>   <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">bool</span> HasMore { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
</span><span style="color: rgba(0, 128, 128, 1)">57</span> }</pre>
</div>
<div>&nbsp;</div>
<div>二、懒加载控件视图和数据逻辑</div>
<div>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> &lt;<span style="color: rgba(0, 0, 0, 1)">UserControl
</span><span style="color: rgba(0, 128, 128, 1)">2</span>   x:Class=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">LazyComboBoxFinalDemo.Controls.LazyComboBox</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">3</span>   xmlns=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">http://schemas.microsoft.com/winfx/2006/xaml/presentation</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">4</span>   xmlns:x=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">http://schemas.microsoft.com/winfx/2006/xaml</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">5</span>   xmlns:local=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">clr-namespace:LazyComboBoxFinalDemo.Controls</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;
<span style="color: rgba(0, 128, 128, 1)">6</span>   &lt;UserControl.Resources&gt;
<span style="color: rgba(0, 128, 128, 1)">7</span>         &lt;local:ZeroToVisibleConverter x:Key=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ZeroToVisibleConverter</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)">8</span>         &lt;!--清除按钮样式:透明背景、图标--&gt;
<span style="color: rgba(0, 128, 128, 1)">9</span>         &lt;Style x:Key=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ClearButtonStyle</span><span style="color: rgba(128, 0, 0, 1)">"</span> TargetType=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Button</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;
<span style="color: rgba(0, 128, 128, 1)"> 10</span>             &lt;Setter Property=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Background</span><span style="color: rgba(128, 0, 0, 1)">"</span> Value=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Transparent</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)"> 11</span>             &lt;Setter Property=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">BorderThickness</span><span style="color: rgba(128, 0, 0, 1)">"</span> Value=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">0</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)"> 12</span>             &lt;Setter Property=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Padding</span><span style="color: rgba(128, 0, 0, 1)">"</span> Value=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">0</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)"> 13</span>             &lt;Setter Property=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Cursor</span><span style="color: rgba(128, 0, 0, 1)">"</span> Value=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Hand</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)"> 14</span>             &lt;Setter Property=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Template</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;
<span style="color: rgba(0, 128, 128, 1)"> 15</span>               &lt;Setter.Value&gt;
<span style="color: rgba(0, 128, 128, 1)"> 16</span>                     &lt;ControlTemplate TargetType=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Button</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;
<span style="color: rgba(0, 128, 128, 1)"> 17</span>                         &lt;ContentPresenter HorizontalAlignment=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Center</span><span style="color: rgba(128, 0, 0, 1)">"</span> VerticalAlignment=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Center</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)"> 18</span>                     &lt;/ControlTemplate&gt;
<span style="color: rgba(0, 128, 128, 1)"> 19</span>               &lt;/Setter.Value&gt;
<span style="color: rgba(0, 128, 128, 1)"> 20</span>             &lt;/Setter&gt;
<span style="color: rgba(0, 128, 128, 1)"> 21</span>         &lt;/Style&gt;
<span style="color: rgba(0, 128, 128, 1)"> 22</span>         &lt;!--ToggleButton 样式--&gt;
<span style="color: rgba(0, 128, 128, 1)"> 23</span>         &lt;Style x:Key=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ComboToggleButtonStyle</span><span style="color: rgba(128, 0, 0, 1)">"</span> TargetType=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ToggleButton</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;
<span style="color: rgba(0, 128, 128, 1)"> 24</span>             &lt;Setter Property=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Background</span><span style="color: rgba(128, 0, 0, 1)">"</span> Value=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">White</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)"> 25</span>             &lt;Setter Property=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">BorderBrush</span><span style="color: rgba(128, 0, 0, 1)">"</span> Value=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">#CCC</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)"> 26</span>             &lt;Setter Property=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">BorderThickness</span><span style="color: rgba(128, 0, 0, 1)">"</span> Value=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">1</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)"> 27</span>             &lt;Setter Property=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Padding</span><span style="color: rgba(128, 0, 0, 1)">"</span> Value=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">4</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)"> 28</span>             &lt;Setter Property=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Template</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;
<span style="color: rgba(0, 128, 128, 1)"> 29</span>               &lt;Setter.Value&gt;
<span style="color: rgba(0, 128, 128, 1)"> 30</span>                     &lt;ControlTemplate TargetType=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ToggleButton</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;
<span style="color: rgba(0, 128, 128, 1)"> 31</span>                         &lt;<span style="color: rgba(0, 0, 0, 1)">Border
</span><span style="color: rgba(0, 128, 128, 1)"> 32</span>                           Padding=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">{TemplateBinding Padding}</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)"> 33</span>                           Background=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">{TemplateBinding Background}</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)"> 34</span>                           BorderBrush=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">{TemplateBinding BorderBrush}</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)"> 35</span>                           BorderThickness=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">{TemplateBinding BorderThickness}</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)"> 36</span>                           CornerRadius=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">4</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;
<span style="color: rgba(0, 128, 128, 1)"> 37</span>                           &lt;Grid&gt;
<span style="color: rgba(0, 128, 128, 1)"> 38</span>                                 &lt;Grid.ColumnDefinitions&gt;
<span style="color: rgba(0, 128, 128, 1)"> 39</span>                                     &lt;ColumnDefinition /&gt;
<span style="color: rgba(0, 128, 128, 1)"> 40</span>                                     &lt;ColumnDefinition Width=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">20</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)"> 41</span>                                     &lt;ColumnDefinition Width=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">20</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)"> 42</span>                                 &lt;/Grid.ColumnDefinitions&gt;
<span style="color: rgba(0, 128, 128, 1)"> 43</span>                                 &lt;!--按钮文本--&gt;
<span style="color: rgba(0, 128, 128, 1)"> 44</span>                                 &lt;<span style="color: rgba(0, 0, 0, 1)">ContentPresenter
</span><span style="color: rgba(0, 128, 128, 1)"> 45</span>                                     Grid.Column=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">0</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)"> 46</span>                                     Margin=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">4,0,0,0</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)"> 47</span>                                     VerticalAlignment=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Center</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)"> 48</span>                                     Content=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">{TemplateBinding Content}</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)"> 49</span>                                 &lt;!--箭头--&gt;
<span style="color: rgba(0, 128, 128, 1)"> 50</span>                                 &lt;<span style="color: rgba(0, 0, 0, 1)">Path
</span><span style="color: rgba(0, 128, 128, 1)"> 51</span>                                     x:Name=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Arrow</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)"> 52</span>                                     Grid.Column=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">2</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)"> 53</span>                                     VerticalAlignment=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Center</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)"> 54</span>                                     Data=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">M 0 0 L 4 4 L 8 0 Z</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)"> 55</span>                                     Fill=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Gray</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)"> 56</span>                                     RenderTransformOrigin=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">0.5,0.5</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;
<span style="color: rgba(0, 128, 128, 1)"> 57</span>                                     &lt;Path.RenderTransform&gt;
<span style="color: rgba(0, 128, 128, 1)"> 58</span>                                       &lt;RotateTransform Angle=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">0</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)"> 59</span>                                     &lt;/Path.RenderTransform&gt;
<span style="color: rgba(0, 128, 128, 1)"> 60</span>                                 &lt;/Path&gt;
<span style="color: rgba(0, 128, 128, 1)"> 61</span>                                 &lt;!--清除按钮--&gt;
<span style="color: rgba(0, 128, 128, 1)"> 62</span>                                 &lt;<span style="color: rgba(0, 0, 0, 1)">Button
</span><span style="color: rgba(0, 128, 128, 1)"> 63</span>                                     x:Name=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">PART_ClearButton</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)"> 64</span>                                     Grid.Column=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">1</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)"> 65</span>                                     Width=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">16</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)"> 66</span>                                     Height=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">16</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)"> 67</span>                                     VerticalAlignment=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Center</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)"> 68</span>                                     Click=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">OnClearClick</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)"> 69</span>                                     Style=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">{StaticResource ClearButtonStyle}</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)"> 70</span>                                     Visibility=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Collapsed</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;
<span style="color: rgba(0, 128, 128, 1)"> 71</span>                                     &lt;<span style="color: rgba(0, 0, 0, 1)">Path
</span><span style="color: rgba(0, 128, 128, 1)"> 72</span>                                       Data=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">M0,0 L8,8 M8,0 L0,8</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)"> 73</span>                                       Stroke=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Gray</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)"> 74</span>                                       StrokeThickness=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">2</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)"> 75</span>                                 &lt;/Button&gt;
<span style="color: rgba(0, 128, 128, 1)"> 76</span>
<span style="color: rgba(0, 128, 128, 1)"> 77</span>                           &lt;/Grid&gt;
<span style="color: rgba(0, 128, 128, 1)"> 78</span>                         &lt;/Border&gt;
<span style="color: rgba(0, 128, 128, 1)"> 79</span>                         &lt;ControlTemplate.Triggers&gt;
<span style="color: rgba(0, 128, 128, 1)"> 80</span>                           &lt;Trigger Property=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">IsMouseOver</span><span style="color: rgba(128, 0, 0, 1)">"</span> Value=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">True</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;
<span style="color: rgba(0, 128, 128, 1)"> 81</span>                                 &lt;Setter TargetName=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">PART_ClearButton</span><span style="color: rgba(128, 0, 0, 1)">"</span> Property=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Visibility</span><span style="color: rgba(128, 0, 0, 1)">"</span> Value=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Visible</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)"> 82</span>                           &lt;/Trigger&gt;
<span style="color: rgba(0, 128, 128, 1)"> 83</span>                           &lt;DataTrigger Binding=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">{Binding IsOpen, ElementName=PART_Popup}</span><span style="color: rgba(128, 0, 0, 1)">"</span> Value=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">True</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;
<span style="color: rgba(0, 128, 128, 1)"> 84</span>                                 &lt;Setter TargetName=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Arrow</span><span style="color: rgba(128, 0, 0, 1)">"</span> Property=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">RenderTransform</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;
<span style="color: rgba(0, 128, 128, 1)"> 85</span>                                     &lt;Setter.Value&gt;
<span style="color: rgba(0, 128, 128, 1)"> 86</span>                                       &lt;RotateTransform Angle=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">180</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)"> 87</span>                                     &lt;/Setter.Value&gt;
<span style="color: rgba(0, 128, 128, 1)"> 88</span>                                 &lt;/Setter&gt;
<span style="color: rgba(0, 128, 128, 1)"> 89</span>                           &lt;/DataTrigger&gt;
<span style="color: rgba(0, 128, 128, 1)"> 90</span>                         &lt;/ControlTemplate.Triggers&gt;
<span style="color: rgba(0, 128, 128, 1)"> 91</span>                     &lt;/ControlTemplate&gt;
<span style="color: rgba(0, 128, 128, 1)"> 92</span>               &lt;/Setter.Value&gt;
<span style="color: rgba(0, 128, 128, 1)"> 93</span>             &lt;/Setter&gt;
<span style="color: rgba(0, 128, 128, 1)"> 94</span>         &lt;/Style&gt;
<span style="color: rgba(0, 128, 128, 1)"> 95</span>         &lt;!--ListBoxItem 悬停/选中样式--&gt;
<span style="color: rgba(0, 128, 128, 1)"> 96</span>         &lt;Style TargetType=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ListBoxItem</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;
<span style="color: rgba(0, 128, 128, 1)"> 97</span>             &lt;Setter Property=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">HorizontalContentAlignment</span><span style="color: rgba(128, 0, 0, 1)">"</span> Value=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Stretch</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)"> 98</span>             &lt;Setter Property=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Template</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;
<span style="color: rgba(0, 128, 128, 1)"> 99</span>               &lt;Setter.Value&gt;
<span style="color: rgba(0, 128, 128, 1)">100</span>                     &lt;ControlTemplate TargetType=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ListBoxItem</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;
<span style="color: rgba(0, 128, 128, 1)">101</span>                         &lt;<span style="color: rgba(0, 0, 0, 1)">Border
</span><span style="color: rgba(0, 128, 128, 1)">102</span>                           x:Name=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Bd</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">103</span>                           Padding=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">4</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">104</span>                           Background=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Transparent</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;
<span style="color: rgba(0, 128, 128, 1)">105</span>                           &lt;ContentPresenter /&gt;
<span style="color: rgba(0, 128, 128, 1)">106</span>                         &lt;/Border&gt;
<span style="color: rgba(0, 128, 128, 1)">107</span>                         &lt;ControlTemplate.Triggers&gt;
<span style="color: rgba(0, 128, 128, 1)">108</span>                           &lt;Trigger Property=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">IsMouseOver</span><span style="color: rgba(128, 0, 0, 1)">"</span> Value=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">True</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;
<span style="color: rgba(0, 128, 128, 1)">109</span>                                 &lt;Setter TargetName=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Bd</span><span style="color: rgba(128, 0, 0, 1)">"</span> Property=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Background</span><span style="color: rgba(128, 0, 0, 1)">"</span> Value=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">#EEE</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)">110</span>                           &lt;/Trigger&gt;
<span style="color: rgba(0, 128, 128, 1)">111</span>                           &lt;Trigger Property=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">IsSelected</span><span style="color: rgba(128, 0, 0, 1)">"</span> Value=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">True</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;
<span style="color: rgba(0, 128, 128, 1)">112</span>                                 &lt;Setter TargetName=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Bd</span><span style="color: rgba(128, 0, 0, 1)">"</span> Property=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Background</span><span style="color: rgba(128, 0, 0, 1)">"</span> Value=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">#CCC</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)">113</span>                           &lt;/Trigger&gt;
<span style="color: rgba(0, 128, 128, 1)">114</span>                         &lt;/ControlTemplate.Triggers&gt;
<span style="color: rgba(0, 128, 128, 1)">115</span>                     &lt;/ControlTemplate&gt;
<span style="color: rgba(0, 128, 128, 1)">116</span>               &lt;/Setter.Value&gt;
<span style="color: rgba(0, 128, 128, 1)">117</span>             &lt;/Setter&gt;
<span style="color: rgba(0, 128, 128, 1)">118</span>         &lt;/Style&gt;
<span style="color: rgba(0, 128, 128, 1)">119</span>         &lt;!--Popup 边框--&gt;
<span style="color: rgba(0, 128, 128, 1)">120</span>         &lt;Style x:Key=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">PopupBorder</span><span style="color: rgba(128, 0, 0, 1)">"</span> TargetType=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Border</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;
<span style="color: rgba(0, 128, 128, 1)">121</span>             &lt;Setter Property=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">CornerRadius</span><span style="color: rgba(128, 0, 0, 1)">"</span> Value=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">5</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)">122</span>             &lt;Setter Property=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Background</span><span style="color: rgba(128, 0, 0, 1)">"</span> Value=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">White</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)">123</span>             &lt;Setter Property=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">BorderBrush</span><span style="color: rgba(128, 0, 0, 1)">"</span> Value=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">#CCC</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)">124</span>             &lt;Setter Property=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">BorderThickness</span><span style="color: rgba(128, 0, 0, 1)">"</span> Value=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">2</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)">125</span>             &lt;Setter Property=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Padding</span><span style="color: rgba(128, 0, 0, 1)">"</span> Value=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">10</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)">126</span>         &lt;/Style&gt;
<span style="color: rgba(0, 128, 128, 1)">127</span>         &lt;!--水印 TextBox--&gt;
<span style="color: rgba(0, 128, 128, 1)">128</span>         &lt;Style x:Key=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">WatermarkTextBox</span><span style="color: rgba(128, 0, 0, 1)">"</span> TargetType=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">TextBox</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;
<span style="color: rgba(0, 128, 128, 1)">129</span>             &lt;Setter Property=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Template</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;
<span style="color: rgba(0, 128, 128, 1)">130</span>               &lt;Setter.Value&gt;
<span style="color: rgba(0, 128, 128, 1)">131</span>                     &lt;ControlTemplate TargetType=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">TextBox</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;
<span style="color: rgba(0, 128, 128, 1)">132</span>                         &lt;Grid&gt;
<span style="color: rgba(0, 128, 128, 1)">133</span>                           &lt;ScrollViewer x:Name=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">PART_ContentHost</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)">134</span>                           &lt;<span style="color: rgba(0, 0, 0, 1)">TextBlock
</span><span style="color: rgba(0, 128, 128, 1)">135</span>                                 Margin=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">4,2,0,0</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">136</span>                                 Foreground=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Gray</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">137</span>                                 IsHitTestVisible=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">False</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">138</span>                                 Text=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">搜索…</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">139</span>                                 Visibility=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">{Binding Text.Length, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource ZeroToVisibleConverter}}</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)">140</span>                         &lt;/Grid&gt;
<span style="color: rgba(0, 128, 128, 1)">141</span>                     &lt;/ControlTemplate&gt;
<span style="color: rgba(0, 128, 128, 1)">142</span>               &lt;/Setter.Value&gt;
<span style="color: rgba(0, 128, 128, 1)">143</span>             &lt;/Setter&gt;
<span style="color: rgba(0, 128, 128, 1)">144</span>         &lt;/Style&gt;
<span style="color: rgba(0, 128, 128, 1)">145</span>   &lt;/UserControl.Resources&gt;
<span style="color: rgba(0, 128, 128, 1)">146</span>   &lt;Grid&gt;
<span style="color: rgba(0, 128, 128, 1)">147</span>         &lt;<span style="color: rgba(0, 0, 0, 1)">ToggleButton
</span><span style="color: rgba(0, 128, 128, 1)">148</span>             x:Name=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">PART_Toggle</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">149</span>             Click=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">OnToggleClick</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">150</span>             Style=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">{StaticResource ComboToggleButtonStyle}</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;
<span style="color: rgba(0, 128, 128, 1)">151</span>             &lt;Grid&gt;
<span style="color: rgba(0, 128, 128, 1)">152</span>               &lt;!--显示文本--&gt;
<span style="color: rgba(0, 128, 128, 1)">153</span>               &lt;<span style="color: rgba(0, 0, 0, 1)">TextBlock
</span><span style="color: rgba(0, 128, 128, 1)">154</span>                     Margin=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">4,0,24,0</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">155</span>                     VerticalAlignment=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Center</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">156</span>                     Text=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">{Binding DisplayText, RelativeSource={RelativeSource AncestorType=UserControl}}</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)">157</span>               &lt;!--箭头已在模板内,略--&gt;
<span style="color: rgba(0, 128, 128, 1)">158</span>             &lt;/Grid&gt;
<span style="color: rgba(0, 128, 128, 1)">159</span>         &lt;/ToggleButton&gt;
<span style="color: rgba(0, 128, 128, 1)">160</span>         &lt;<span style="color: rgba(0, 0, 0, 1)">Popup
</span><span style="color: rgba(0, 128, 128, 1)">161</span>             x:Name=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">PART_Popup</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">162</span>             AllowsTransparency=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">True</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">163</span>             PlacementTarget=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">{Binding ElementName=PART_Toggle}</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">164</span>             PopupAnimation=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Fade</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">165</span>             StaysOpen=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">False</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;
<span style="color: rgba(0, 128, 128, 1)">166</span>             &lt;!--AllowsTransparency 启用透明,PopupAnimation 弹窗动画--&gt;
<span style="color: rgba(0, 128, 128, 1)">167</span>             &lt;Border Width=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">{Binding ActualWidth, ElementName=PART_Toggle}</span><span style="color: rgba(128, 0, 0, 1)">"</span> Style=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">{StaticResource PopupBorder}</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;
<span style="color: rgba(0, 128, 128, 1)">168</span>               &lt;Border.Effect&gt;
<span style="color: rgba(0, 128, 128, 1)">169</span>                     &lt;<span style="color: rgba(0, 0, 0, 1)">DropShadowEffect
</span><span style="color: rgba(0, 128, 128, 1)">170</span>                         BlurRadius=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">15</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">171</span>                         Opacity=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">0.7</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">172</span>                         ShadowDepth=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">0</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">173</span>                         Color=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">#e6e6e6</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)">174</span>               &lt;/Border.Effect&gt;
<span style="color: rgba(0, 128, 128, 1)">175</span>               &lt;Grid Height=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">300</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;
<span style="color: rgba(0, 128, 128, 1)">176</span>                     &lt;Grid.RowDefinitions&gt;
<span style="color: rgba(0, 128, 128, 1)">177</span>                         &lt;RowDefinition Height=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Auto</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)">178</span>                         &lt;RowDefinition Height=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">*</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)">179</span>                     &lt;/Grid.RowDefinitions&gt;
<span style="color: rgba(0, 128, 128, 1)">180</span>                     &lt;!--搜索框--&gt;
<span style="color: rgba(0, 128, 128, 1)">181</span>                     &lt;<span style="color: rgba(0, 0, 0, 1)">TextBox
</span><span style="color: rgba(0, 128, 128, 1)">182</span>                         x:Name=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">PART_SearchBox</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">183</span>                         Margin=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">0,0,0,8</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">184</span>                         VerticalAlignment=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Center</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">185</span>                         Style=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">{StaticResource WatermarkTextBox}</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">186</span>                         TextChanged=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">OnSearchChanged</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)">187</span>                     &lt;!--列表--&gt;
<span style="color: rgba(0, 128, 128, 1)">188</span>                     &lt;<span style="color: rgba(0, 0, 0, 1)">ListBox
</span><span style="color: rgba(0, 128, 128, 1)">189</span>                         x:Name=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">PART_List</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">190</span>                         Grid.Row=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">1</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">191</span>                         DisplayMemberPath=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ItemText</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">192</span>                         ItemsSource=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">{Binding Items, RelativeSource={RelativeSource AncestorType=UserControl}}</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">193</span>                         ScrollViewer.CanContentScroll=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">True</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">194</span>                         ScrollViewer.ScrollChanged=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">OnScroll</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">195</span>                         SelectionChanged=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">OnSelectionChanged</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">196</span>                         VirtualizingStackPanel.IsVirtualizing=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">True</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 128, 128, 1)">197</span>                         VirtualizingStackPanel.VirtualizationMode=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Recycling</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
<span style="color: rgba(0, 128, 128, 1)">198</span>               &lt;/Grid&gt;
<span style="color: rgba(0, 128, 128, 1)">199</span>             &lt;/Border&gt;
<span style="color: rgba(0, 128, 128, 1)">200</span>         &lt;/Popup&gt;
<span style="color: rgba(0, 128, 128, 1)">201</span>   &lt;/Grid&gt;
<span style="color: rgba(0, 128, 128, 1)">202</span> &lt;/UserControl&gt;</pre>
</div>
<div class="cnblogs_code"><img src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif"><img id="code_img_opened_8fd744fa-f3f9-4a97-86d2-da9de468594c" class="code_img_opened lazyload" style="display: none" data-src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif">
<div id="cnblogs_code_open_8fd744fa-f3f9-4a97-86d2-da9de468594c" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">partial</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> LazyComboBox : UserControl, INotifyPropertyChanged
</span><span style="color: rgba(0, 128, 128, 1)"> 2</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 3</span>      <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">readonly</span> DependencyProperty ItemsProviderProperty =
<span style="color: rgba(0, 128, 128, 1)"> 4</span>          DependencyProperty.Register(nameof(ItemsProvider), <span style="color: rgba(0, 0, 255, 1)">typeof</span>(ILazyDataProvider&lt;ComboItem&gt;<span style="color: rgba(0, 0, 0, 1)">),
</span><span style="color: rgba(0, 128, 128, 1)"> 5</span>            <span style="color: rgba(0, 0, 255, 1)">typeof</span>(LazyComboBox), <span style="color: rgba(0, 0, 255, 1)">new</span> PropertyMetadata(<span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">));
</span><span style="color: rgba(0, 128, 128, 1)"> 6</span>
<span style="color: rgba(0, 128, 128, 1)"> 7</span>      <span style="color: rgba(0, 0, 255, 1)">public</span> ILazyDataProvider&lt;ComboItem&gt;<span style="color: rgba(0, 0, 0, 1)"> ItemsProvider
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span> <span style="color: rgba(0, 0, 0, 1)">   {
</span><span style="color: rgba(0, 128, 128, 1)"> 9</span>          <span style="color: rgba(0, 0, 255, 1)">get</span> =&gt; (ILazyDataProvider&lt;ComboItem&gt;<span style="color: rgba(0, 0, 0, 1)">)GetValue(ItemsProviderProperty);
</span><span style="color: rgba(0, 128, 128, 1)">10</span>          <span style="color: rgba(0, 0, 255, 1)">set</span> =&gt;<span style="color: rgba(0, 0, 0, 1)"> SetValue(ItemsProviderProperty, value);
</span><span style="color: rgba(0, 128, 128, 1)">11</span> <span style="color: rgba(0, 0, 0, 1)">   }
</span><span style="color: rgba(0, 128, 128, 1)">12</span>
<span style="color: rgba(0, 128, 128, 1)">13</span>      <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">readonly</span> DependencyProperty SelectedItemProperty =
<span style="color: rgba(0, 128, 128, 1)">14</span>          DependencyProperty.Register(nameof(SelectedItem), <span style="color: rgba(0, 0, 255, 1)">typeof</span><span style="color: rgba(0, 0, 0, 1)">(ComboItem),
</span><span style="color: rgba(0, 128, 128, 1)">15</span>            <span style="color: rgba(0, 0, 255, 1)">typeof</span><span style="color: rgba(0, 0, 0, 1)">(LazyComboBox),
</span><span style="color: rgba(0, 128, 128, 1)">16</span>            <span style="color: rgba(0, 0, 255, 1)">new</span> FrameworkPropertyMetadata(<span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnSelectedItemChanged));
</span><span style="color: rgba(0, 128, 128, 1)">17</span>
<span style="color: rgba(0, 128, 128, 1)">18</span>      <span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> ComboItem SelectedItem
</span><span style="color: rgba(0, 128, 128, 1)">19</span> <span style="color: rgba(0, 0, 0, 1)">   {
</span><span style="color: rgba(0, 128, 128, 1)">20</span>          <span style="color: rgba(0, 0, 255, 1)">get</span> =&gt;<span style="color: rgba(0, 0, 0, 1)"> (ComboItem)GetValue(SelectedItemProperty);
</span><span style="color: rgba(0, 128, 128, 1)">21</span>          <span style="color: rgba(0, 0, 255, 1)">set</span> =&gt;<span style="color: rgba(0, 0, 0, 1)"> SetValue(SelectedItemProperty, value);
</span><span style="color: rgba(0, 128, 128, 1)">22</span> <span style="color: rgba(0, 0, 0, 1)">   }
</span><span style="color: rgba(0, 128, 128, 1)">23</span>
<span style="color: rgba(0, 128, 128, 1)">24</span>      <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> OnSelectedItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
</span><span style="color: rgba(0, 128, 128, 1)">25</span> <span style="color: rgba(0, 0, 0, 1)">   {
</span><span style="color: rgba(0, 128, 128, 1)">26</span>          <span style="color: rgba(0, 0, 255, 1)">if</span> (d <span style="color: rgba(0, 0, 255, 1)">is</span><span style="color: rgba(0, 0, 0, 1)"> LazyComboBox ctrl)
</span><span style="color: rgba(0, 128, 128, 1)">27</span> <span style="color: rgba(0, 0, 0, 1)">         {
</span><span style="color: rgba(0, 128, 128, 1)">28</span> <span style="color: rgba(0, 0, 0, 1)">             ctrl.Notify(nameof(DisplayText));
</span><span style="color: rgba(0, 128, 128, 1)">29</span> <span style="color: rgba(0, 0, 0, 1)">         }
</span><span style="color: rgba(0, 128, 128, 1)">30</span> <span style="color: rgba(0, 0, 0, 1)">   }
</span><span style="color: rgba(0, 128, 128, 1)">31</span>
<span style="color: rgba(0, 128, 128, 1)">32</span>      <span style="color: rgba(0, 0, 255, 1)">public</span> ObservableCollection&lt;ComboItem&gt; Items { <span style="color: rgba(0, 0, 255, 1)">get</span>; } = <span style="color: rgba(0, 0, 255, 1)">new</span> ObservableCollection&lt;ComboItem&gt;<span style="color: rgba(0, 0, 0, 1)">();
</span><span style="color: rgba(0, 128, 128, 1)">33</span>      <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">string</span> _currentFilter = <span style="color: rgba(128, 0, 0, 1)">""</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">34</span>      <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">int</span> _currentPage = <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">35</span>      <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">const</span> <span style="color: rgba(0, 0, 255, 1)">int</span> PageSize = <span style="color: rgba(128, 0, 128, 1)">30</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">36</span>      <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">bool</span> HasMore { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
</span><span style="color: rgba(0, 128, 128, 1)">37</span>      <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">string</span> DisplayText =&gt; SelectedItem?.ItemText ?? <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">请选择...</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">38</span>
<span style="color: rgba(0, 128, 128, 1)">39</span>      <span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)"> LazyComboBox()
</span><span style="color: rgba(0, 128, 128, 1)">40</span> <span style="color: rgba(0, 0, 0, 1)">   {
</span><span style="color: rgba(0, 128, 128, 1)">41</span> <span style="color: rgba(0, 0, 0, 1)">         InitializeComponent();
</span><span style="color: rgba(0, 128, 128, 1)">42</span> <span style="color: rgba(0, 0, 0, 1)">   }
</span><span style="color: rgba(0, 128, 128, 1)">43</span>
<span style="color: rgba(0, 128, 128, 1)">44</span>      <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">event</span><span style="color: rgba(0, 0, 0, 1)"> PropertyChangedEventHandler PropertyChanged;
</span><span style="color: rgba(0, 128, 128, 1)">45</span>      <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Notify(<span style="color: rgba(0, 0, 255, 1)">string</span> prop) =&gt; PropertyChanged?.Invoke(<span style="color: rgba(0, 0, 255, 1)">this</span>, <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> PropertyChangedEventArgs(prop));
</span><span style="color: rgba(0, 128, 128, 1)">46</span>
<span style="color: rgba(0, 128, 128, 1)">47</span>      <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">async</span> <span style="color: rgba(0, 0, 255, 1)">void</span> LoadPage(<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> pageIndex)
</span><span style="color: rgba(0, 128, 128, 1)">48</span> <span style="color: rgba(0, 0, 0, 1)">   {
</span><span style="color: rgba(0, 128, 128, 1)">49</span>          <span style="color: rgba(0, 0, 255, 1)">if</span> (ItemsProvider == <span style="color: rgba(0, 0, 255, 1)">null</span>) <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">50</span>          <span style="color: rgba(0, 0, 255, 1)">var</span> result = <span style="color: rgba(0, 0, 255, 1)">await</span><span style="color: rgba(0, 0, 0, 1)"> ItemsProvider.FetchAsync(_currentFilter, pageIndex, PageSize);
</span><span style="color: rgba(0, 128, 128, 1)">51</span>          <span style="color: rgba(0, 0, 255, 1)">if</span> (pageIndex == <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">) Items.Clear();
</span><span style="color: rgba(0, 128, 128, 1)">52</span>          <span style="color: rgba(0, 0, 255, 1)">foreach</span> (<span style="color: rgba(0, 0, 255, 1)">var</span> it <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> result.Items) Items.Add(it);
</span><span style="color: rgba(0, 128, 128, 1)">53</span>          HasMore =<span style="color: rgba(0, 0, 0, 1)"> result.HasMore;
</span><span style="color: rgba(0, 128, 128, 1)">54</span>          PART_Popup.IsOpen = <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">55</span> <span style="color: rgba(0, 0, 0, 1)">   }
</span><span style="color: rgba(0, 128, 128, 1)">56</span>
<span style="color: rgba(0, 128, 128, 1)">57</span>      <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span> OnClearClick(<span style="color: rgba(0, 0, 255, 1)">object</span><span style="color: rgba(0, 0, 0, 1)"> sender, RoutedEventArgs e)
</span><span style="color: rgba(0, 128, 128, 1)">58</span> <span style="color: rgba(0, 0, 0, 1)">   {
</span><span style="color: rgba(0, 128, 128, 1)">59</span>          e.Handled = <span style="color: rgba(0, 0, 255, 1)">true</span>;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 阻止事件冒泡,不触发 Toggle 打开</span>
<span style="color: rgba(0, 128, 128, 1)">60</span>          SelectedItem = <span style="color: rgba(0, 0, 255, 1)">null</span>; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 清空选中</span>
<span style="color: rgba(0, 128, 128, 1)">61</span>          Notify(nameof(DisplayText)); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 刷新按钮文本</span>
<span style="color: rgba(0, 128, 128, 1)">62</span>          PART_Popup.IsOpen = <span style="color: rgba(0, 0, 255, 1)">false</span>;   <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 确保关掉弹窗</span>
<span style="color: rgba(0, 128, 128, 1)">63</span> <span style="color: rgba(0, 0, 0, 1)">   }
</span><span style="color: rgba(0, 128, 128, 1)">64</span>
<span style="color: rgba(0, 128, 128, 1)">65</span>      <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span> OnToggleClick(<span style="color: rgba(0, 0, 255, 1)">object</span><span style="color: rgba(0, 0, 0, 1)"> sender, RoutedEventArgs e)
</span><span style="color: rgba(0, 128, 128, 1)">66</span> <span style="color: rgba(0, 0, 0, 1)">   {
</span><span style="color: rgba(0, 128, 128, 1)">67</span>          _currentPage = <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">68</span>          LoadPage(<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">69</span>          PART_Popup.IsOpen = <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">70</span> <span style="color: rgba(0, 0, 0, 1)">   }
</span><span style="color: rgba(0, 128, 128, 1)">71</span>
<span style="color: rgba(0, 128, 128, 1)">72</span>      <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span> OnSearchChanged(<span style="color: rgba(0, 0, 255, 1)">object</span><span style="color: rgba(0, 0, 0, 1)"> sender, TextChangedEventArgs e)
</span><span style="color: rgba(0, 128, 128, 1)">73</span> <span style="color: rgba(0, 0, 0, 1)">   {
</span><span style="color: rgba(0, 128, 128, 1)">74</span>          _currentFilter =<span style="color: rgba(0, 0, 0, 1)"> PART_SearchBox.Text;
</span><span style="color: rgba(0, 128, 128, 1)">75</span>          _currentPage = <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">76</span>          LoadPage(<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">77</span> <span style="color: rgba(0, 0, 0, 1)">   }
</span><span style="color: rgba(0, 128, 128, 1)">78</span>
<span style="color: rgba(0, 128, 128, 1)">79</span>      <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span> OnScroll(<span style="color: rgba(0, 0, 255, 1)">object</span><span style="color: rgba(0, 0, 0, 1)"> sender, ScrollChangedEventArgs e)
</span><span style="color: rgba(0, 128, 128, 1)">80</span> <span style="color: rgba(0, 0, 0, 1)">   {
</span><span style="color: rgba(0, 128, 128, 1)">81</span>          <span style="color: rgba(0, 0, 255, 1)">if</span> (!HasMore) <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">82</span>          <span style="color: rgba(0, 0, 255, 1)">if</span> (e.VerticalOffset &gt;= e.ExtentHeight - e.ViewportHeight - <span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">83</span>            LoadPage(++<span style="color: rgba(0, 0, 0, 1)">_currentPage);
</span><span style="color: rgba(0, 128, 128, 1)">84</span> <span style="color: rgba(0, 0, 0, 1)">   }
</span><span style="color: rgba(0, 128, 128, 1)">85</span>
<span style="color: rgba(0, 128, 128, 1)">86</span>      <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span> OnSelectionChanged(<span style="color: rgba(0, 0, 255, 1)">object</span><span style="color: rgba(0, 0, 0, 1)"> sender, SelectionChangedEventArgs e)
</span><span style="color: rgba(0, 128, 128, 1)">87</span> <span style="color: rgba(0, 0, 0, 1)">   {
</span><span style="color: rgba(0, 128, 128, 1)">88</span>          <span style="color: rgba(0, 0, 255, 1)">if</span> (PART_List.SelectedItem <span style="color: rgba(0, 0, 255, 1)">is</span><span style="color: rgba(0, 0, 0, 1)"> ComboItem item)
</span><span style="color: rgba(0, 128, 128, 1)">89</span> <span style="color: rgba(0, 0, 0, 1)">         {
</span><span style="color: rgba(0, 128, 128, 1)">90</span>            SelectedItem =<span style="color: rgba(0, 0, 0, 1)"> item;
</span><span style="color: rgba(0, 128, 128, 1)">91</span> <span style="color: rgba(0, 0, 0, 1)">             Notify(nameof(DisplayText));
</span><span style="color: rgba(0, 128, 128, 1)">92</span>            PART_Popup.IsOpen = <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">93</span> <span style="color: rgba(0, 0, 0, 1)">         }
</span><span style="color: rgba(0, 128, 128, 1)">94</span> <span style="color: rgba(0, 0, 0, 1)">   }
</span><span style="color: rgba(0, 128, 128, 1)">95</span>}</pre>
</div>
<span class="cnblogs_code_collapse">LazyComboBox.cs</span></div>
<div class="cnblogs_code"><img id="code_img_closed_3f20c6a2-eb47-4216-b4f0-8a7f8459cfff" class="code_img_closed lazyload" data-src="http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif"><img id="code_img_opened_3f20c6a2-eb47-4216-b4f0-8a7f8459cfff" class="code_img_opened lazyload" style="display: none" data-src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif">
<div id="cnblogs_code_open_3f20c6a2-eb47-4216-b4f0-8a7f8459cfff" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)"> 2</span> <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 下拉弹窗搜索框根据数据显示专用转换器
</span><span style="color: rgba(0, 128, 128, 1)"> 3</span> <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 用于将0转换为可见
</span><span style="color: rgba(0, 128, 128, 1)"> 4</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)"> 5</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> ZeroToVisibleConverter : IValueConverter
</span><span style="color: rgba(0, 128, 128, 1)"> 6</span> <span style="color: rgba(0, 0, 0, 1)">{
</span><span style="color: rgba(0, 128, 128, 1)"> 7</span>   <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">object</span> Convert(<span style="color: rgba(0, 0, 255, 1)">object</span> value, Type targetType, <span style="color: rgba(0, 0, 255, 1)">object</span><span style="color: rgba(0, 0, 0, 1)"> parameter, CultureInfo culture)
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span> <span style="color: rgba(0, 0, 0, 1)">    {
</span><span style="color: rgba(0, 128, 128, 1)"> 9</span>         <span style="color: rgba(0, 0, 255, 1)">if</span> (value <span style="color: rgba(0, 0, 255, 1)">is</span> <span style="color: rgba(0, 0, 255, 1)">int</span> i &amp;&amp; i == <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">10</span>             <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Visibility.Visible;
</span><span style="color: rgba(0, 128, 128, 1)">11</span>         <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> Visibility.Collapsed;
</span><span style="color: rgba(0, 128, 128, 1)">12</span> <span style="color: rgba(0, 0, 0, 1)">    }
</span><span style="color: rgba(0, 128, 128, 1)">13</span>
<span style="color: rgba(0, 128, 128, 1)">14</span>   <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">object</span> ConvertBack(<span style="color: rgba(0, 0, 255, 1)">object</span> value, Type targetType, <span style="color: rgba(0, 0, 255, 1)">object</span><span style="color: rgba(0, 0, 0, 1)"> parameter, CultureInfo culture)
</span><span style="color: rgba(0, 128, 128, 1)">15</span>         =&gt; <span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> NotImplementedException();
</span><span style="color: rgba(0, 128, 128, 1)">16</span> }</pre>
</div>
<span class="cnblogs_code_collapse">转换器</span></div>
<div>&nbsp;</div>
<div>三、视图页面使用示例</div>
<div>
<div class="cnblogs_code">
<pre>xmlns:ctrl=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">clr-namespace:LazyComboBoxFinalDemo.Controls</span><span style="color: rgba(128, 0, 0, 1)">"</span>
&lt;Grid Margin=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">10</span><span style="color: rgba(128, 0, 0, 1)">"</span>&gt;
    &lt;<span style="color: rgba(0, 0, 0, 1)">ctrl:LazyComboBox
      Width</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">200</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
      Height</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">40</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
      ItemsProvider</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">{Binding MyDataProvider}</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
      SelectedItem</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">{Binding PartSelectedItem, Mode=TwoWay}</span><span style="color: rgba(128, 0, 0, 1)">"</span> /&gt;
&lt;/Grid&gt;</pre>
</div>
<div class="cnblogs_code">
<pre></pre>
<div>//对应视图的VM中绑定数据:</div>
<pre><span style="color: rgba(0, 0, 255, 1)">public</span> ILazyDataProvider&lt;ComboItem&gt; MyDataProvider { <span style="color: rgba(0, 0, 255, 1)">get</span><span style="color: rgba(0, 0, 0, 1)">; }
    </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ComboItemProvider();

</span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
<span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 当前选择值
</span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
<span style="color: rgba(0, 0, 0, 1)">
</span><span style="color: rgba(0, 0, 255, 1)">private</span> ComboItem partSelectedItem;</pre>
</div>
<p>&nbsp;</p>
<div>四、效果图</div>
<div>
<p><img alt="" loading="lazy" src="https://img2024.cnblogs.com/blog/1038506/202504/1038506-20250430104243801-823109338.png"></p>
<p><img src="https://img2024.cnblogs.com/blog/1038506/202504/1038506-20250430104248943-789164665.png"></p>
<p>&nbsp;</p>
</div>
<div>&nbsp;</div>
</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
</div>
</div>
</div><br><br>
来源:https://www.cnblogs.com/adingfirstlove/p/18855065
頁: [1]
查看完整版本: WPF封装一个懒加载下拉列表控件(支持搜索)