防止隐藏控件的绑定

时间:2011-06-26 06:42:13

标签: c# wpf xaml data-binding

我有几个堆栈面板,我只想显示所选的一个(来自另一个组合框)。 如您所见,在stackpanel内部有一个组合框,它将选定的值绑定到一个对象。

我的问题是每个面板都会更新并覆盖对象,甚至是隐藏的对象! 是否可以防止隐藏对象的绑定?

<StackPanel x:Name="pnl_1" Orientation="Horizontal"
            Visibility="{Binding SelectedItem.Name,ElementName=comboProp, Mode=OneWay, ConverterParameter=pnl_1,  Converter={StaticResource PanelVisibilityConverter},FallbackValue=Collapsed}">
            <ComboBox Height="23" Width="90"                                 
                      ItemsSource="{Binding Source={StaticResource Source1}}"                                                                  
                      SelectedValue="{Binding Path=Data.Operand, Converter={StaticResource Converter1}}">
            </ComboBox>

</StackPanel>


<StackPanel x:Name="pnl_2" Orientation="Horizontal"
            Visibility="{Binding SelectedItem.Name,ElementName=comboProp, Mode=OneWay, ConverterParameter=pnl_2,  Converter={StaticResource PanelVisibilityConverter},FallbackValue=Collapsed}">
            <ComboBox Height="23" Width="90"                                 
                      ItemsSource="{Binding Source={StaticResource Source2}}"                                                                  
                      SelectedValue="{Binding Path=Data.Operand, Converter={StaticResource Converter2}}">
            </ComboBox>

</StackPanel>

3 个答案:

答案 0 :(得分:1)

将数据绑定到不可见的UIElement没有任何问题,只要它不会导致性能问题。

如果要根据可见性设置数据绑定,则必须在源代码中执行此操作;你不能在XAML中做到这一点。

以下是如何动态创建绑定的示例:

Binding myBinding = new Binding("Data.Operand");
myBinding.Source = myItemsSource;
BindingOperations.SetBinding(myComboBox, ComboBox.SelectedValueProperty, myBinding);

要清除绑定,您将使用

BindingOperations.ClearBinding(myComboBox, ComboBox.SelectedValueProperty);

答案 1 :(得分:0)

您可以使用DataTriggers使绑定成为条件,这里是一个ListBox的示例,如果它周围的边框可见,则只设置ItemsSource

<ListBox Height="100" ScrollViewer.HorizontalScrollBarVisibility="Auto"
        ScrollViewer.VerticalScrollBarVisibility="Auto">
    <ListBox.Style>
        <Style TargetType="{x:Type ListBox}">
            <Style.Triggers>
                <DataTrigger
                        Binding="{Binding Visibility, RelativeSource={RelativeSource AncestorType=Border}}"
                        Value="Visible">
                    <Setter Property="ItemsSource"
                            Value="{Binding Source={x:Static local:App.Log}, Path=Buffer}" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </ListBox.Style>
</ListBox>

答案 2 :(得分:0)

是的,这是可能的。 我是在类及其子类的情况下完成的。 我的例子可能不像你的情况,但原则可能很适用。

我有一个A类和两个A的子类,名为AB和AC。 AC和AB都有额外的属性,高于A的属性。

然后有一个包含As,AB和AC的ObservableCollection。 我必须显示Collection的DataGrid和Collection元素的各个成员的StackPanel。

对于AB类和AC类的额外成员,我在XAML中定义了两个StaticResource StackPanel。 (我总是要显示基类A的成员,所以这些成员都在这个结构之外。)

 <StackPanel  x:Key="AB"...../>
 <StackPanel  x:Key="AC"...../>
 <StackPanel  x:Key="Nothing"...../>

这些StackPanel,因为它们是资源,在运行时通常不会绑定:只有当它们被绑定到!时。 现在我定义一个ContentControl,绑定到一个名为&#34; SubClassPanel&#34;的属性:

 public StackPanel SubClassPanel {get; set; etc...}

现在,如果您只想显示基类,我可以通过编程方式将SubClassPanel设置为使用AB资源或AC资源或空的虚拟StackPanel资源。 这是子类StackPanels的插入点的XAML:

 <ContentControl Content="{Binding SubClassPanel,
          Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>

在我的情况下,使用DataGrid事件&#34; SelectionChanged&#34;完成了更改。这是活动经理:

 public void ChangeSection(object sender, SelectionChangedEventArgs e)
    {
        // sender is the datagrid
        if (sender == null)
            return;
        // So, SelectedItem can be of class A, AB or AC:
        var s = (sender as DataGrid).SelectedItem;

        if (s is AB)
            (s as AB).SubClassPanel = this.FindResource("AB") as StackPanel;
        else
        {
            if (s is AC)
                (s as AC).SubClassPanel = this.FindResource("AC") as StackPanel;
            else
            {
                 // or show just the base class members: 
                 (s).SubClassPanel = this.FindResource("Nothing") as StackPanel;
            }
        }
    }