user3342256
user3342256

Reputation: 1290

WPF Shared DataContext / Binding

I have an issue with my binding in WPF currently. I have a two-tabbed application. The first tab contains a datagrid control that is populated by a list. The second tab contains a listbox control that is populated by a list. The problem is if I run the check on the first tab and it returns for example 5 rows in the datagrid, the second tab will populate 5 dummy listbox items. So the controls are evidently sharing the some context, but I'm unsure how to correct that.

XAML for first tab showing binding:

<DataGrid Name="WinUpdateDataGrid" Margin="10,79,0,114" ItemsSource="{Binding}" CanUserAddRows="false" AutoGenerateColumns="true" HorizontalAlignment="Left" VerticalAlignment="Center" ColumnWidth="*" Height="161" Width="509" MaxHeight="150" MaxWidth="700"></DataGrid>

Code for first tab showing datacontext:

 private void CheckforWindowsUpdates_Click(object sender, RoutedEventArgs e)
    {
        CheckforWindowsUpdates.IsEnabled = false;
        WinUpdateStatusText.Text = "Evaluation in progress...";
        WinUpdateProgressBar.Visibility = Visibility.Visible;

        WinUpdateProgressBar.IsIndeterminate = true;

        worker = new BackgroundWorker();
        worker.WorkerReportsProgress = true;
        worker.WorkerSupportsCancellation = true;

        DataContext = WindowsUpdate.updateClassList;

        worker.DoWork += delegate(object s, DoWorkEventArgs args)
        {
            WindowsUpdate.getCollectionofMissingSecurityUpdates(WindowsUpdate.windowsKBExceptionsList, WindowsUpdate.CabFilePath);
        };

        worker.ProgressChanged += delegate(object s, ProgressChangedEventArgs args)
        {

        };

        worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args)
        {
            CheckforWindowsUpdates.IsEnabled = true;
            WinUpdateStatusText.Text = "Evaluation completed. Missing the following updates:";
            WinUpdateProgressBar.IsIndeterminate = false;
            WinUpdateProgressBar.Visibility = Visibility.Hidden;


            if (WindowsUpdate.updateClassList.Count > 0)
            {
                WinUpdateDataGrid.Visibility = Visibility.Visible;
                DownloadandInstallWinUpdatesButton.Visibility = Visibility.Visible;
            }
            else
            {
                WinUpdateDataGrid.Visibility = Visibility.Hidden;
                WinUpdateStatusText.Text = "Evaluation completed. No missing updates.";
            }

        };

        worker.RunWorkerAsync();

    }

XAML for second tab:

<ListBox Name="ThirdPartyListBox" ItemsSource="{Binding}" Margin="0,70,0,0">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal">
                                <Image Source="C:\Users\Test\Desktop\Project\ACME-WPF\ACME-WPF\window-new-3.ico" Margin="5" Width="50"/>
                                <Button Name="ThirdPartyInstallButton" Content="Install" Click="InstallThirdPartyUpdatesButton_Click" Margin="5,5,0,0" Height="25"></Button>
                                <Button Name="ThirdPartyPostoneButton" Content="Postpone" Margin="5,5,0,0" Height="25"></Button>
                                <TextBlock FontWeight="Bold" Text="{Binding Item2.Name}" Margin="12,25,0,0"/>
                                <TextBlock FontWeight="Bold" Text="{Binding Item2.RequiredVersion}" Margin="3,25,0,0"/>
                                <TextBlock Text="{Binding Item2.CustomUIMessage}" Margin="10,25,0,0" TextWrapping="Wrap" Foreground="Red"/>
                                <TextBlock Text="You have used " Margin="3,25,0,0"/>
                                <TextBlock Text="{Binding Item3.UsedDeferrals}" Margin="3,25,0,0"/>
                                <TextBlock Text=" of " Margin="3,25,0,0"/>
                                <TextBlock Text="{Binding Item2.MaxDefferals}" Margin="3,25,0,0"/>
                                <TextBlock Text=" deferrals for this update." Margin="3,25,0,0"/>
                            </StackPanel>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>

Code for second tab:

 private void CheckforThirdPartyUpdatesButton_Click(object sender, RoutedEventArgs e)
    {
        CheckforThirdPartyUpdatesButton.IsEnabled = false;

        worker = new BackgroundWorker();
        worker.WorkerReportsProgress = true;
        worker.WorkerSupportsCancellation = true;

        DataContext = RegScan_ThirdParty.comparisonListWithState;

        worker.DoWork += delegate(object s, DoWorkEventArgs args)
        {
            MainEntry.checkFor3PUpdates();
        };

        worker.ProgressChanged += delegate(object s, ProgressChangedEventArgs args)
        {

        };

        worker.RunWorkerCompleted += delegate(object s, RunWorkerCompletedEventArgs args)
        {


            CheckforThirdPartyUpdatesButton.IsEnabled = true;
        };

        worker.RunWorkerAsync();
    }

Full XAML by request:

<Window x:Class="ACME_WPF.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="ACME" Height="411.085" MaxWidth="555.668"
    SizeToContent="WidthAndHeight" WindowStartupLocation="CenterScreen"
    WindowStyle="ToolWindow"
    >
<Grid>
    <TabControl>
        <TabItem Header="Windows Updates">
            <Grid>
                <Image Name="WindowsUpdateDefaultImage" Source="C:\Users\Test\Desktop\Project\ACME-WPF\ACME-WPF\windowsupdate.png" Margin="0,16,488,286" Width="50"/>
                <TextBlock Name="WinUpdateStatusText" Width="Auto" HorizontalAlignment="Left" Margin="267,22,0,0" TextWrapping="Wrap" Text="{Binding Path=WindowsUpdateCompliance, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" FontSize="14" Foreground="DarkSlateBlue"/>
                <Button Name="CheckforWindowsUpdates" HorizontalAlignment="Left" Margin="54,18,0,0" VerticalAlignment="Top" Width="207" Content="Check for Windows Security Updates" Height="25" Click="CheckforWindowsUpdates_Click"/>
                <ProgressBar Name="WinUpdateProgressBar" HorizontalAlignment="Left" Height="18" Margin="54,52,0,0" VerticalAlignment="Top" Width="207"/>
                <DataGrid Name="WinUpdateDataGrid" Margin="10,79,0,114" ItemsSource="{Binding}" CanUserAddRows="false" AutoGenerateColumns="true" HorizontalAlignment="Left" VerticalAlignment="Center" ColumnWidth="*" Height="161" Width="509" MaxHeight="150" MaxWidth="700"></DataGrid>
                <Button Name="DownloadandInstallWinUpdatesButton" Content="Download and Install Windows Updates" HorizontalAlignment="Left" Margin="10,250,0,0" VerticalAlignment="Top" Width="227" Height="26" Click="DownloadandInstallWinUpdatesButton_Click"/>
                <ProgressBar Name="DownloadandInstallWinUpdatesButtonProgressBar" HorizontalAlignment="Left" Height="26" Margin="10,286,0,0" VerticalAlignment="Top" Width="227"/>
                <TextBlock Name="WinUpdateInstallationText" HorizontalAlignment="Left" Margin="256,250,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="Auto"/>
            </Grid>
        </TabItem>
        <TabItem Header="Third Party Updates">
            <Grid>
                <Button Name="CheckforThirdPartyUpdatesButton" Content="Check for Third Party Updates" Margin="10,11,339,304" Click="CheckforThirdPartyUpdatesButton_Click" MaxWidth="200"/>
                <ListBox Name="ThirdPartyListBox" ItemsSource="{Binding}" Margin="0,70,0,0">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Horizontal">
                                <Image Source="C:\Users\Test\Desktop\Project\ACME-WPF\ACME-WPF\window-new-3.ico" Margin="5" Width="50"/>
                                <Button Name="ThirdPartyInstallButton" Content="Install" Click="InstallThirdPartyUpdatesButton_Click" CommandParameter="{Binding Path=.}" Command="{Binding ElementName=ThirdPartyListBox, Path=DataContext.InstallComponentCommand}" Margin="5,5,0,0" Height="25"></Button>
                                <Button Name="ThirdPartyPostoneButton" Content="Postpone" Margin="5,5,0,0" Height="25"></Button>
                                <TextBlock FontWeight="Bold" Text="{Binding Item2.Name}" Margin="12,25,0,0"/>
                                <TextBlock FontWeight="Bold" Text="{Binding Item2.RequiredVersion}" Margin="3,25,0,0"/>
                                <TextBlock Text="{Binding Item2.CustomUIMessage}" Margin="10,25,0,0" TextWrapping="Wrap" Foreground="Red"/>
                                <TextBlock Text="You have used " Margin="3,25,0,0"/>
                                <TextBlock Text="{Binding Item3.UsedDeferrals}" Margin="3,25,0,0"/>
                                <TextBlock Text=" of " Margin="3,25,0,0"/>
                                <TextBlock Text="{Binding Item2.MaxDefferals}" Margin="3,25,0,0"/>
                                <TextBlock Text=" deferrals for this update." Margin="3,25,0,0"/>
                            </StackPanel>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
            </Grid>
        </TabItem>
        <TabItem Header="Information">
            <Grid>
                <Label Name="Info_ComputerNameLabel" Content="Computer Name: " Margin="10,13,397,253" RenderTransformOrigin="0.49,1"/>
                <Label Name="Info_UserNameLabel" Content="User Name: " Width="100" Margin="10,54,419,222"/>
                <Label Name="Info_IPAddressLabel" Content="IP Address: " Width="100" Margin="10,96,419,180"/>
                <TextBlock Name="Info_ComputerNameText" HorizontalAlignment="Left" Margin="137,18,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top"/>
                <TextBlock Name="Info_UserNameText" HorizontalAlignment="Left" Margin="137,59,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top"/>
                <TextBlock Name="Info_IPAddressText" HorizontalAlignment="Left" Margin="137,101,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top"/>
            </Grid>
        </TabItem>
    </TabControl>
</Grid>

Upvotes: 0

Views: 1665

Answers (2)

Terje
Terje

Reputation: 130

My guess would be that you need to set the DataContext specifically to the Grid and the ListBox. Something like this:

WinUpdateDataGrid.DataContext = WindowsUpdate.updateClassList;

and

ThirdPartyListBox.DataContext = RegScan_ThirdParty.comparisonListWithState;

The thing is that if the two functions CheckforWindowsUpdates_Click and CheckforThirdPartyUpdatesButton_Click is precent in the same codebehind file they will set the same DataContext and the binding ItemsSource="{Binding}" in the Grid and the ListBox will inherit the same DataContext.

Upvotes: 1

123 456 789 0
123 456 789 0

Reputation: 10865

Short answer:{Binding} is not a shortcut for "binding to itself" (in the sense of RelativeSource.Self). Rather, {Binding} is equivalent to {Binding Path=.}, which binds to the current source.


To elaborate: A binding has a source and a path. You can do a "binding to itself", for example, by using

<myUIControl myProperty="{Binding RelativeSource={RelativeSource Self}, Path=x}" />

This, however, sets the source to the control itself, so it will try to access property x of the UI control (rather than property x of the current data context). From how I understood your question, this is not what you want; in particular, it is not what {Binding} does: {Binding} keeps the source as it is (usually the DataContext of some parent element) and binds to the source itself (equivalent to Path=.).

It's possible that your current source for two controls are being shared. I would just explicitly set the Binding datasource rather than doing the shortcut method

Update: It is really sharing the DataContext. Can you just create two public properties for those DataContext and do the Binding from there. Don't forget to implement INotifyPropertyChanged and call the implementation when the properties are being set. That way it is more clear and readable to other developers that there are really two datacontext for two different controls.

Upvotes: 0

Related Questions