【发布时间】:2016-10-22 12:49:48
【问题描述】:
上下文
网络上的服务器定期使用 UDP 公布其名称。
数据报从 1967 端口进入并包含如下字符串:
UiProxy SomeServerMachineName
添加了新条目,更新了现有条目,并且陈旧的条目在用作 XAML 组合框的 ItemsSource 的可观察集合中过期。
这是组合框
<ComboBox x:Name="comboBox" ItemsSource="{Binding Directory}" />
这是支持代码。异常处理程序包含所有危险的东西,但为简洁起见在这里省略。
public class HostEntry
{
public string DisplayName { get; set;}
public HostName HostName { get; set; }
public DateTime LastUpdate { get; set; }
public HostEntry(string displayname, HostName hostname)
{
DisplayName = displayname;
HostName = hostname;
LastUpdate = DateTime.Now;
}
public override string ToString()
{
return DisplayName;
}
}
HostEntry _selectedHost;
public HostEntry SelectedHost
{
get { return _selectedHost; }
set
{
_selectedHost = value;
UpdateWriter();
}
}
async UpdateWriter() {
if (_w != null)
{
_w.Dispose();
_w = null;
Debug.WriteLine("Disposed of old writer");
}
if (SelectedHost != null)
{
_w = new DataWriter(await _ds.GetOutputStreamAsync(SelectedHost.HostName, "1967"));
Debug.WriteLine(string.Format("Created new writer for {0}", SelectedHost));
}
}
ObservableCollection<HostEntry> _directory = new ObservableCollection<HostEntry>();
public ObservableCollection<HostEntry> Directory
{
get { return _directory; }
}
private async void _ds_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
if (_dispatcher == null) return;
await _dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
var dr = args.GetDataReader();
var raw = dr.ReadString(dr.UnconsumedBufferLength);
var s = raw.Split();
if (s[0] == "UiProxy")
{
if (_directory.Any(x => x.ToString() == s[1]))
{ //update
_directory.Single(x => x.ToString() == s[1]).LastUpdate = DateTime.Now;
}
else
{ //insert
_directory.Add(new HostEntry(s[1], args.RemoteAddress));
}
var cutoff = DateTime.Now.AddSeconds(-10);
var stale = _directory.Where(x => x.LastUpdate < cutoff);
foreach (var item in stale) //delete
_directory.Remove(item);
}
});
}
集合开始为空。
从 SelectedHost 的 setter 调用的 UpdateWrite 方法会销毁(如果需要)并在 DatagramSocket 周围创建(如果可能)一个 DataWriter,目标是 SelectedHost 的值所描述的地址。
目标
在添加值且列表不再为空时自动选择。
列表也可以变为为空。发生这种情况时,选择必须以 -1 的选定索引返回 null。
就目前而言,列表是受管理的,并且可以从列表中交互式地选择一个服务器。
目前我正在像这样设置 SelectedHost,但我确信它可以通过绑定来完成。
private void comboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
SelectedHost = comboBox.SelectedItem as HostEntry;
}
SelectedHost 的 setter 方法调用 CreateWriter,它管理在别处使用的对象以将数据发送到选定的主机。我从 setter 中调用了它,因为它必须始终在值更改后立即发生,并且不能在其他时间发生。它在一个方法中,所以它可以是异步的。
我可以将它移动到 SelectionChanged 处理程序,但如果我这样做了,我如何保证执行顺序?
问题
当我尝试以编程方式设置组合框的选择时出现错误。我正在编组到 UI 线程,但情况仍然不好。这样做的正确方法是什么?我试过设置 SelectedIndex 和 SelectedValue。
【问题讨论】:
-
你遇到了什么错误?