简体   繁体   English

WPF共享的DataContext /绑定

[英]WPF Shared DataContext / Binding

I have an issue with my binding in WPF currently. 我目前在WPF中的绑定存在问题。 I have a two-tabbed application. 我有一个两选项卡的应用程序。 The first tab contains a datagrid control that is populated by a list. 第一个选项卡包含一个由列表填充的datagrid控件。 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. 问题是如果我在第一个选项卡上运行检查,并且它在数据网格中返回例如5行,则第二个选项卡将填充5个虚拟列表框项。 So the controls are evidently sharing the some context, but I'm unsure how to correct that. 因此,控件显然共享某些上下文,但是我不确定如何更正。

XAML for first tab showing binding: 第一个选项卡的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>

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

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: 根据要求提供完整的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>

My guess would be that you need to set the DataContext specifically to the Grid and the ListBox. 我的猜测是您需要将DataContext专门设置为Grid和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. 问题是,如果两个函数CheckforWindowsUpdates_ClickCheckforThirdPartyUpdatesButton_Click在同一代码隐藏文件中占CheckforThirdPartyUpdatesButton_Click则它们将在网格中设置相同的DataContext和绑定ItemsSource="{Binding}" ,并且ListBox将继承相同的DataContext。

Short answer : {Binding} is not a shortcut for "binding to itself" (in the sense of RelativeSource.Self ). 简短答案{Binding} 不是 “绑定到自身”的快捷方式(就RelativeSource.Self而言 )。 Rather, {Binding} is equivalent to {Binding Path=.} , which binds to the current source. 相反, {Binding} 等效于 {Binding Path=.} ,它绑定到当前源。


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). 然而,这将源头上控制自己,所以它会尝试访问属性x (而不是财产的UI控件的x当前数据上下文)。 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=. ). 特别是,它不是{Binding}所做的: {Binding}将源保持不变(通常是某些父元素的DataContext )并绑定到源本身(等效于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 我只是显式设置Binding数据源,而不是使用快捷方式

Update : It is really sharing the DataContext. 更新 :它实际上是共享DataContext。 Can you just create two public properties for those DataContext and do the Binding from there. 您可以为这些DataContext创建两个公共属性,然后从那里进行Binding吗? Don't forget to implement INotifyPropertyChanged and call the implementation when the properties are being set. 不要忘记实现INotifyPropertyChanged并在设置属性时调用实现。 That way it is more clear and readable to other developers that there are really two datacontext for two different controls. 这样一来,其他开发人员就更清楚易读,两个不同的控件实际上有两个数据datacontext

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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