简体   繁体   English

WPF,绑定到相关ComboBox的属性始终提供初始值

[英]WPF, property bound to dependent ComboBox always gives initial value

I have a ComboBox that needs to depend on the value of another ComboBox . 我有一个ComboBox ,它需要依赖于另一个ComboBox的值。 This part already works, with the dependent ComboBox refreshing when a new value is chosen in the independent ComboBox : 在独立的ComboBox选择新值时,此部分已经起作用,并且依赖的ComboBox刷新:

<!-- Independent -->
<ComboBox Height="23" HorizontalAlignment="Left" Grid.Row="2" Grid.Column="2"
          x:Name="cbo_product" VerticalAlignment="Center" Width="120"
          ItemsSource="{Binding Source={StaticResource productsXml}}"
          DisplayMemberPath="@name" SelectedValuePath="@name"
          SelectionChanged="cbo_product_SelectionChanged"
          SelectedValue="{Binding Path=Product}" />

<!-- Dependent -->
<ComboBox Height="23" HorizontalAlignment="Left" Grid.Row="3" Grid.Column="2"
          x:Name="cbo_component" VerticalAlignment="Center" Width="201"
          DataContext="{Binding SelectedItem, ElementName=cbo_product}"
          ItemsSource="{Binding XPath=Components/Component}"
          DisplayMemberPath="@name" SelectedValuePath="@name"
          SelectedValue="{Binding Path=Component}"
          SelectionChanged="cbo_component_SelectionChanged" />

In the C# class behind this, I have: 在此后面的C#类中,我有:

public MyUserControlConstructor()
{
    MyViewModelInstance= new MyViewModel();
    DataContext = MyViewModelInstance;
}

And in MyViewModel , I have: MyViewModel ,我有:

public string Component
{
    get { return _component; }
    set
    {
        if (value == _component)
        {
            return;
        }
        _component = value;
        onPropertyChanged(PropertyNames.Component);
    }
}

private void onPropertyChanged(PropertyNames fieldName)
{
    if (null == PropertyChanged)
    {
        return;
    }
    string propertyName = Enum.GetName(typeof(PropertyNames), fieldName);
    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}

When I change the dependent ComboBox (Component), it shows up with the new value in my app, of course. 当然,当我更改依赖的ComboBox (组件)时,它会在我的应用程序中显示新值。 However, when I hit a button that causes the value of the Component property to be displayed, it is always the initial value, and not the value I just chose in the ComboBox . 但是,当我按下导致显示Component属性值的按钮时,它始终是初始值,而不是我刚刚在ComboBox选择的值。 I think there must be an error in my XAML. 我认为XAML中肯定有错误。 For the C#, I tried to follow a combination of this and this guide . 对于C#,我试图遵循的组合这个本指南 How do I tie my dependent ComboBox to XML values nested in the SelectedItem of the independent ComboBox , but still update the Component property in my class? 如何将我的从属ComboBox绑定到嵌套在独立ComboBoxSelectedItem中的XML值,但仍更新类中的Component属性?

Edit: my suspicion is that things are wonky because I set the DataContext for the dependent ComboBox in two places: first in the constructor in C#, to my view model, and second in the XAML, to DataContext="{Binding SelectedItem, ElementName=cbo_product}" . 编辑:我的怀疑是,事情很古怪,因为我在两个地方设置了依赖ComboBoxDataContext :首先在C#的构造函数中,设置为我的视图模型,第二在XAML中,设置为DataContext="{Binding SelectedItem, ElementName=cbo_product}"

Edit: I had been setting initial values in the constructor to my view model class. 编辑:我已经在构造函数中为我的视图模型类设置了初始值。 When I take out the initial value for the Component property, then even after I change the selected value in the dependent ComboBox , I still get no value from the Component property. 当我取出Component属性的初始值时,即使更改了相关ComboBox的选定值,我仍然无法从Component属性中得到任何值。 This pretty much just rehashes what I already knew: the dependent ComboBox is tied to the independent ComboBox (it gets its data from the independent ComboBox , that is), but not to the Component property. 这几乎可以改写我已经知道的内容:依赖的ComboBox绑定到独立的ComboBox (它从独立的ComboBox获取数据),而不是Component属性。

Edit: by request, here's a sample of my XML: 编辑:根据要求,这是我的XML示例:

<Products xmlns="">
  <Product name="Awesomeness">
    <Components>
      <Component name="Component of Glory"/>
      <Component name="Component of Doom"/>
    </Components>
  </Product>
</Products>

Edit: I'm guessing a MultiBinding would be of use, after looking at this and this . 编辑:在查看thisthis之后,我猜想MultiBinding是有用的。

Edit: it seems like I should be able to get the dependent ComboBox to work without setting DataContext , just by using ItemsSource : 编辑:似乎我应该能够通过使用ItemsSource而不设置DataContext来使依赖的ComboBox工作:

<ComboBox Height="23" HorizontalAlignment="Left" Grid.Row="3" Grid.Column="2"
                      x:Name="cbo_component" VerticalAlignment="Center" Width="201"
                      ItemsSource="{Binding ElementName=cbo_product, Path=SelectedItem,
                          XPath=Components/Component}"
                      DisplayMemberPath="@name" SelectedValuePath="@name"
                      SelectedValue="{Binding Path=Component}"
                      SelectionChanged="cbo_component_SelectionChanged"/>

However, this doesn't work: the dependent ComboBox is empty, instead of showing all the Component names. 但是,这不起作用:依赖的ComboBox为空,而不是显示所有组件名称。

The way I found of getting around this involves setting the ItemsSource in C# instead of XAML, which I would prefer not to do. 我发现解决此问题的方法涉及在C#中设置ItemsSource而不是XAML,我希望这样做。 However, it works, and after a day and a half of banging on this, it's the best I came up with. 但是,它起作用了,经过一天半的努力,这是我想到的最好的方法。

In XAML: 在XAML中:

<!-- Independent -->
<ComboBox Height="23" HorizontalAlignment="Left" Grid.Row="2" Grid.Column="2"
          x:Name="cbo_product" VerticalAlignment="Center" Width="120"
          ItemsSource="{Binding Source={StaticResource productsXml}}"
          DisplayMemberPath="@name" SelectedValuePath="@name"
          SelectionChanged="cbo_product_SelectionChanged"
          SelectedItem="{Binding Path=ProductNode}"
          SelectedValue="{Binding Path=Product}" />

<!-- Dependent -->
<ComboBox Height="23" HorizontalAlignment="Left" Grid.Row="3" Grid.Column="2"
          x:Name="cbo_component" VerticalAlignment="Center" Width="201"
          DisplayMemberPath="@name" SelectedValuePath="@name"
          SelectedValue="{Binding Path=Component, Mode=TwoWay}"
          SelectionChanged="cbo_component_SelectionChanged"/>

In C#, the event handler for when the independent ComboBox changes: 在C#中,独立ComboBox发生更改时的事件处理程序:

private void cbo_product_SelectionChanged(object sender,
    SelectionChangedEventArgs e)
{
    // Set ItemsSource of dependent ComboBox
    cbo_component.ItemsSource = getChildNodesFromComboBox(
        sender as ComboBox, "Components/Component"
    );
    cbo_component.SelectedIndex = 0;
}

// Helper method to do XPath query and get child nodes from selected value of
// independent ComboBox
private XmlNodeList getChildNodesFromComboBox(ComboBox comboBox,
    string xpath)
{
    if (null == comboBox)
    {
        return null;
    }
    var xml = comboBox.SelectedItem as XmlElement;
    if (null == xml)
    {
        return null;
    }
    return xml.SelectNodes(xpath);
}

Now the Component property in my view model class, to which my dependent ComboBox is bound in XAML, gets populated with the value selected in the dependent ComboBox because I didn't have to change the DataContext of the dependent ComboBox . 现在,我的视图模型类中的依赖项(在XAML中绑定到我的依赖ComboBox )的Component属性填充了在依赖ComboBox选择的值,因为我不必更改依赖ComboBoxDataContext

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM