简体   繁体   中英

StaticResource mixed with ItemSource in TabControl

I have an UserControl. At the top, there is a global parameter, bound to a static property in the class MultiSliceCommand . Below, there is a TabControl, populated by a Template and bound to public static ObservableCollection<GroupContainer> groups , also a property in MultiSliceCommand . GroupContainer contains various properties, mainly doubles, ints etc., displayed and editable in textboxes in the TabItems.

When I now change a value in TabItem, the corresponding property in the correct element of groups is set. However, when I close & reopen the dialog, the all the GroupContainers in groups are reset to their defaults - even the properties not bound at any point to the dialog.

Changes to the global variables (outside of the TabControl) are preserved correctly. Changes to the TabControl are also preserved correctly if I remove the binding to the global variables - in explicit, if I remove the lines <local:MultiSliceCommand x:Key="mutliSliceCommand" /> and <TextBox x:Name="Mm_Per_Package" Text="{Binding Source={StaticResource mutliSliceCommand}, Path=Mm_Per_Package}" />

How can I change the bindings to preserve the changes to the global variable as well as the contents of the Tabs when closing & reopening the dialog?

The Xaml File:

<UserControl.Resources>
    <DataTemplate x:Key="HeaderTemplate">
        <Label Content="{Binding Group_Name}" />
    </DataTemplate>

    <local:MultiSliceCommand x:Key="mutliSliceCommand" />

    <DataTemplate x:Key="ItemTemplate">
        <Grid>
            <TextBox x:Name="_length" Text="{Binding Path=Length, UpdateSourceTrigger=PropertyChanged, Delay=0}"  />
        </Grid>
    </DataTemplate>
</UserControl.Resources>

<ScrollViewer>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <GroupBox
            Header="Global Parameters"
            Grid.Row="0"
            Grid.Column="0"
            >
            <Grid Height="Auto" Width="Auto">
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>

                <TextBox x:Name="Mm_Per_Package" Text="{Binding Source={StaticResource mutliSliceCommand}, Path=Mm_Per_Package}" />
            </Grid>
        </GroupBox>

        <GroupBox
            Header="Materials"
            Grid.Row="1"
            Grid.Column="0"
            Grid.ColumnSpan="2"
            >
            <TabControl x:Name="TabControl1"
            HorizontalAlignment="Left" 
            VerticalAlignment="Top"
            ItemTemplate="{StaticResource HeaderTemplate}" 
            ContentTemplate="{StaticResource ItemTemplate}"
                        />
        </GroupBox>
        <!--
        <Button Content="Save settings"
            Grid.Row="2"
            HorizontalAlignment="Right"
            Margin="10,10,0,0"
            VerticalAlignment="Top"
            Width="75" 
            Click="Btn_Save"    />-->
    </Grid>
</ScrollViewer>

The Class MultiSliceCommand

public class MultiSliceCommand
{
    public static ObservableCollection<GroupContainer> groups { get; set; }
    private static double _mm_per_package { get; set; } = 0;
    public static double Mm_Per_Package
    {
        get { return _mm_per_package; }
        set { _mm_per_package = value < 0 ? 0 : value; }
    }

    public MultiSliceCommand()
    {
       groups = new ObservableCollection<GroupContainer>
        {
            new GroupContainer("Group 1"),
            new GroupContainer("Group 1"),
            new GroupContainer("Group 3")
        };
    }  
}

The class ObjectContainer

public class GroupContainer : INotifyPropertyChanged
{
   private double _length { get; set; } = 0;


    public double Length
    {
        get { return _length; }
        set { _length = value < 0 ? 0 : value;  NotifyPropertyChanged("Min_Vector_Length"); }
    }

    // Methods
    public GroupContainer(string group_name)
    {
              }


    // Helper Stuff
    public event PropertyChangedEventHandler PropertyChanged;
    protected void NotifyPropertyChanged(string sProp)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(sProp));
        }
    }
}

Ok, fixed it with an (somewhat dirty) hack:

I just outsourced the global variable to its own class, and bind the xaml to this class. In MultiSliceCommand , I use getter / setter on the property to just relay the value from the "isolation class"

Isolation class:

public class xaml_backend_variables
{
    private static double _mm_per_package = 0;
    public static double Mm_Per_Package
    {
        get { return _mm_per_package; }
        set { _mm_per_package = value < 0 ? 0 : value; }
    }

    public xaml_backend_variables()
    {

    }
}

MultiSliceCommand

 public static double Mm_Per_Package
    {
        get { return xaml_backend_variables.Mm_Per_Package; }
        set { xaml_backend_variables.Mm_Per_Package = value; }
    }

XAML Modifications

....
<local:xaml_backend_variables x:Key="xaml_backend_variables" />
....
<TextBox x:Name="Mm_Per_Package" Text="{Binding Source={StaticResource xaml_backend_variables}, Path=Mm_Per_Package}" />

But now all values are preserved correctly when closing and reopening the dialog.

Still, if someone has an explanation why this happens and what would be the correct / elegant way to solve this, I would like very much to know!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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