开发者

Prevent binding from hidden control

I have couple of stack panels, I only want to show the one that was selected (from another combobox). As you can see, inside stackpanel there is a combobox that binds the selected value to an object.

My problem is that every panel updates and overrides the object, even the one that is hidden!

Is it possible to prevent binding from hidden objects?

<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}}"                                      开发者_StackOverflow中文版                            
                      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>


There is nothing wrong with having a data binding to an invisible UIElement, as long as it does not cause performance problems.

If you want to set data binding depending on visibility, you must do that in your source code; you cannot do it in XAML.

Here is an example how to create the binding dynamically:

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

And to clear the binding you would use

BindingOperations.ClearBinding(myComboBox, ComboBox.SelectedValueProperty);


You can make bindings conditional using DataTriggers, here's an example of a ListBox which only has its ItemsSource set if the Border around it is visible:

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


Yes, that is possible. I did it in a situation of a class and its subclasses. My example may not be like your situation, but the principle may very well apply.

I have a class A and two subclasses of A, named AB and AC. Both AC and AB have extra properties, above those of A.

Then there is an ObservableCollection containing As, ABs and ACs. I had to display a DataGrid of the Collection and a StackPanel for the individual members of the Collection elements.

For the extra members of class AB and AC, I defined two StaticResource StackPanels in XAML. (I always had to display the members of base class A, so those members are outside this construction.)

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

These StackPanels , because they are resource, will not normally bind during runtime: only when and if they are bound to!. Now I define a ContentControl, bound to a property named "SubClassPanel":

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

Now I can programmatically set SubClassPanel to eihter the AB resource or the AC resource or an empty, dummy StackPanel resource, if you only want to show the base class. Here is the XAML for the insertion point of the subclass StackPanels:

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

The changing is done, in my case, with the DataGrid event "SelectionChanged". Here is the event manager:

 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;
            }
        }
    }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜