0

ComboBox在 XAML 中使用:

 <ComboBox x:Name="Combobox1" ItemsSource="{Binding}" Margin="0,0,300,0"  
           Width="100" FontSize="30"   />

在后面的代码中,我将其值设置为:

 protected override void OnNavigatedTo(NavigationEventArgs e)
 {
     Combobox1.DataContext = ComponentDataSource.ComponentCollection;
 }

现在我有一个数据源:

public class ComponentDataSource
{      
    private static ObservableCollection<ComponentGroup> _componentcollection;    

    public static ObservableCollection<ComponentGroup> ComponentCollection
    {
        get { return _componentcollection; }
    }


    public static async void CheckJson(object sender, object e)
    {
        var client = new HttpClient();
        client.MaxResponseContentBufferSize = 1024 * 1024;

        try
        {
            var response = await client.GetAsync(new Uri("URI"));
            response.EnsureSuccessStatusCode();
            var result = await response.Content.ReadAsStringAsync();
            var jobj = JObject.Parse(result);

            var list = jobj.Children()
                .Cast<JProperty>()
                .Select(p => new ComponentGroup()
                {
                    Name = p.Name,
                    Type = (string)p.Value["P1"],
                    Value = (string)p.Value["P2"]
                })
                .ToList();

            _componentcollection = new ObservableCollection<ComponentGroup>(list);
        }
        catch (HttpRequestException ex)
        {
        }
    }
}

由于某种原因,这些项目没有出现在ComboBox. 我得到的只是一个空的ComboBox.

有人可以帮我吗?

编辑1:嗨,我知道我错过了一些简单的东西,但如果有人可以帮助我,我将不胜感激。顺便说一句,如果您想要代码,请告诉我,我会将其上传到 skydrive。

4

2 回答 2

2

Vasile 在评论中说得对。Windows 8 应用程序中的 XAML 无法绑定到静态属性。XAML 可以像这样绑定到标准属性:

public string Name { get; set; }

那(上图)将与等值绑定。的{Binding Mode=OneTime}。那是因为更新引发事件。同时,您可以使用这样的完全事件属性:

string m_Name = default(string);
public string Name { get { return m_Name; } set { SetProperty(ref m_Name, value); } }

这将在 XAML 中绑定,支持您指定的任何模式 ( OneTime, OneWay, TwoWay)。它遵循INotifyPropertyChanged模式并且非常基本。

我说了这么多就是为了说这个。这两种方法是绑定的唯一方法。您不能绑定到字段。你不能绑定到一个方法(还)。而且您不能绑定到静态属性。如果您必须绑定到静态属性,只需在视图模型的标准属性中公开您的静态属性。

为了向您展示我说的是实话,请考虑以下 XAML(几乎像您的一样):

<ComboBox x:Name="MyCombo" ItemsSource="{Binding}" />

如果你试试这个,它会很好地绑定:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    this.MyCombo.DataContext = new MyModel().Items;
    base.OnNavigatedTo(e);
}

public class MyModel
{
    public MyModel()
    {
        foreach (var item in Enumerable.Range(1, 50))
            Items.Add(item);
    }
    ObservableCollection<int> m_Items = new ObservableCollection<int>();
    public ObservableCollection<int> Items { get { return m_Items; } }
}

两者之间的唯一区别是static零件。因此,即使以您尝试的方式推动价值观也行不通。这是因为您直接绑定到静态属性。

这是一种拥有static 公开它以便绑定的方法:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    this.MyCombo.DataContext = new MyModel().Items;
    base.OnNavigatedTo(e);
}

public class MyModel
{
    public MyModel()
    {
        foreach (var item in Enumerable.Range(1, 50))
            s_Items.Add(item);
    }
    private static ObservableCollection<int> s_Items = new ObservableCollection<int>();
    public ObservableCollection<int> Items { get { return s_Items; } }
}

在上面的代码中,我在类中有值 static MyModel,但我有一个标准属性来公开它。因为它是一个ObservableColelction已经为绑定事件的属性,所以这可能是完整的实现。所以你得到static 绑定。说得通?

现在到了尴尬的部分。

您用来在问题中绑定的技术应该有效。将静态属性DataContext绑定到,然后在ItemsSource工作中绑定到它。@maad0 已经证明这是一种很好的方法。那么,为什么它不适合你。

我想我只能说“这不是因为你绑定错误”。<blush />我很想删除我的答案,但我留下它只是因为静态绑定的解释可能对尝试这样做的开发人员有价值。

用这个测试你的代码

这是您的 CheckJson 方法。我添加了一个调试器语句,看看你是否真的得到了任何结果。尝试在您的应用程序中使用此示例并查看它是否损坏。如果它没有中断,那么问题不在于您没有数据。问题出在您的绑定中。虽然在我看来一切都很好。

public static async void CheckJson(object sender, object e)
{
    var client = new HttpClient();
    client.MaxResponseContentBufferSize = 1024 * 1024;

    try
    {
        var response = await client.GetAsync(new Uri("URI"));
        response.EnsureSuccessStatusCode();
        var result = await response.Content.ReadAsStringAsync();
        var jobj = JObject.Parse(result);

        var list = jobj.Children()
            .Cast<JProperty>()
            .Select(p => new ComponentGroup()
            {
                Name = p.Name,
                Type = (string)p.Value["P1"],
                Value = (string)p.Value["P2"]
            })
            .ToList();

        // add this code
        if (!_componentcollection.Any())
            System.Diagnostics.Debugger.Break();

        _componentcollection = new ObservableCollection<ComponentGroup>(list);
    }
    catch (HttpRequestException ex)
    {
    }
}
于 2013-05-08T15:35:56.540 回答
2

您的代码中有一些内容可能会导致为空ComboBox

  • 您的 Web 服务是否真的返回结果?您正在吞下的那个例外可能会隐藏您实际上正在使用空(或null)列表的事实。这不是你现在的问题,但它可能是。

  • 假设您的集合具有元素,并且由于您使用的是后面的代码,为什么不简单地分配ItemsSource属性?

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        Combobox1.ItemsSource = ComponentDataSource.ComponentCollection;
    }
    

    如果您的收藏不为空,这将显示您的项目。

尽管其他人建议,您的绑定是正确的,因为您没有绑定到静态属性。您正在绑定到一个对象,DataContext并且您将其设置为静态属性的值。如果您的收藏在您将其分配给组合框之前没有null并且具有值,则将显示这些项目。DataContext

我假设在您的情况下发生的事情是,您将其设置DataContext为一个值,null或者在最好的情况下,设置为一个空集合。

您的CheckJson方法看起来非常像 a 的事件处理程序DispatchTimer,因此我假设您定期从 Web 下载元素以将它们显示在您的组合框中。但是,请注意,每次您这样做时,都会将包含它们的集合替换为新的ObservableCollection!

要测试我的两个假设,您所要做的就是CheckJson在分配DataContext.

解决问题的最简单方法,特别是因为您的集合是静态的,是存储ObservableCollection一次_componentcollection(例如,在类的静态构造函数中或在声明它时对其进行初始化),然后根据需要简单地存储Add,RemoveClearitems 。由于您的组合框将始终收听相同的列表,因此会在其内容更改时收到通知。你会有:

private static ObservableCollection<ComponentGroup> _componentcollection = new ObservableCollection<ComponentGroup>();

在 中CheckJson,您替换:

_componentcollection = new ObservableCollection<ComponentGroup>(list);

和:

_componentcollection.Clear();

foreach (var item in list)
{
    _componentcollection.Add(item);
}

PS。上面我的建议,ItemsSource直接使用,将遇到与当前代码完全相同的问题,它只是将绑定从图片中删除并证明绑定不是问题。您仍然必须小心不要替换静态代码中的列表,例如,ObservableCollection按照我在答案结尾处的建议使用单个列表。

于 2013-05-08T15:53:33.020 回答