WPF共享DataContext / Binding

时间:2014-03-18 14:50:25

标签: c# wpf xaml

我目前在WPF中遇到绑定问题。我有一个双标签应用程序。第一个选项卡包含由列表填充的数据网格控件。第二个选项卡包含由列表填充的列表框控件。问题是如果我在第一个选项卡上运行检查并返回数据网格中的示例5行,则第二个选项卡将填充5个虚拟列表框项。所以控件显然是在分享一些背景,但我不确定如何纠正。

显示绑定的第一个选项卡的XAML:

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

显示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:

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

第二个标签的代码:

 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();
    }

按要求提供完整的XAML:

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

2 个答案:

答案 0 :(得分:1)

我的猜测是你需要将DataContext专门设置为Grid和ListBox。像这样:

WinUpdateDataGrid.DataContext = WindowsUpdate.updateClassList;

ThirdPartyListBox.DataContext = RegScan_ThirdParty.comparisonListWithState;

问题在于,如果两个函数CheckforWindowsUpdates_ClickCheckforThirdPartyUpdatesButton_Click在同一个代码隐藏文件中出现,它们将在Grid中设置相同的DataContext和绑定ItemsSource="{Binding}",ListBox将继承相同的DataContext。

答案 1 :(得分:0)

简短回答{Binding} 是&#34;绑定到自身的快捷方式&#34; (在RelativeSource.Self的意义上)。而是{Binding} is equivalent to {Binding Path=.},它绑定到当前来源。


详细说明:绑定包含路径。例如,您可以使用

对自身&#34;进行绑定
<myUIControl myProperty="{Binding RelativeSource={RelativeSource Self}, Path=x}" />

然而,这会将设置为控件本身,因此它将尝试访问UI控件的属性x(而不是当前属性x数据上下文)。从我如何理解你的问题,这不是你想要的;特别是,它不是{Binding}所做的:{Binding}保持源的原样(通常是某个父元素的DataContext)并绑定到源本身(相当于{{1} }})。

您可能正在共享两个控件的当前源。我只是显式设置Path=.数据源而不是快捷方法

<强>更新: 它实际上是在共享DataContext。您可以为Binding创建两个公共属性,然后从那里执行DataContext。不要忘记实现Binding并在设置属性时调用实现。这样,对于其他开发人员来说,两个不同的控件实际上有两个INotifyPropertyChanged更清晰,更易读。