在网络上是定期用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值所描述的地址。
自动选择何时添加值并且列表不再为空。
该列表也可以变为为空。发生这种情况时,选择必须返回null,并且选择的索引为-1。
根据情况,列表是可管理的,并且可以从列表中以交互方式选择服务器。
目前我正在设置SelectedHost,但我相信它可以通过绑定来完成。
private void comboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
SelectedHost = comboBox.SelectedItem as HostEntry;
}
SelectedHost的setter方法调用CreateWriter,它管理在别处使用的对象以将数据发送到所选主机。我已经从setter中调用了它,因为它必须始终在值更改后立即发生,并且在任何时候都不会发生。它在一个方法中,因此它可以是异步的。
我可以将它移动到SelectionChanged处理程序,但如果我这样做,那么我如何保证执行顺序?
当我尝试以编程方式设置组合框的选择时,我收到错误。我正在调整UI线程,但仍然不是很好。这样做的正确方法是什么?我尝试过设置SelectedIndex和SelectedValue。
答案 0 :(得分:0)
当我尝试以编程方式设置组合框的选择时,我收到错误。
你好吗?在代码隐藏中,只要您绑定的集合在该索引处有一个项目,它就应该起作用:
myComboBox.SelectedIndex = 4;
但我相信可以通过绑定来完成
是的,可以,看起来你忘了实施INotifyPropertyChanged。此外,由于您使用的是UWP,因此有一种新的改进的绑定语法Bind
而非Binding
在此处了解更多信息:https://msdn.microsoft.com/en-us/windows/uwp/data-binding/data-binding-in-depth
<ComboBox x:Name="comboBox" ItemsSource="{Binding Directory}"
SelectedItem="{Binding SelectedHost}" />
public event PropertyChangedEventHandler PropertyChanged;
HostEntry _selectedHost;
public HostEntry SelectedHost
{
get { return _selectedHost; }
set
{
_selectedHost = value;
RaiseNotifyPropertyChanged();
// What is this? propertys should not do things like this CreateWriter();
}
}
// This method is called by the Set accessor of each property.
// The CallerMemberName attribute that is applied to the optional propertyName
// parameter causes the property name of the caller to be substituted as an argument.
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}