ComboBox无法设置DataContext

时间:2013-05-08 07:45:27

标签: c# windows-8 windows-store-apps winrt-xaml

我在XAML中使用ComboBox

 <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。

2 个答案:

答案 0 :(得分: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中绑定,支持您指定的任何模式(OneTimeOneWayTwoWay)。它遵循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; } }
}

在上面的代码中,我在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)
    {
    }
}

答案 1 :(得分:2)

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

  • 您的网络服务是否实际返回结果?您吞咽的异常可能会隐藏您实际使用空(或null)列表的事实。这不是你现在的问题,但可能是。

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

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

    如果您的收藏品不为空,这将显示您的商品。

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

我认为在您的情况下发生的情况是,您要将DataContext设置为值null,或者在最佳情况下设置为空集合。

您的CheckJson方法看起来非常像DispatchTimer的事件处理程序,所以我假设您经常从网上下载元素以在组合框中显示它们。但请注意,每次执行此操作时,您都会使用新的ObservableCollection替换包含它们的集合!

要测试我的两个假设,您需要做的就是在分配CheckJson之前调用DataContext(并确保它完全运行)。

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

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