UserControl Binding 每次使用时都必须设置上下文

UserControl Binding have to set context every time i use it

每次我创建一个 UserControl 时,我都必须在每次使用时专门设置 DataContext。尽管我从 parent 知道上下文是正确的。 问题是我还需要在 DataTemplates 中使用它们,但它们永远无法工作。 我试过将堆栈面板的上下文设置为 "elementname=root" 但没有修复它...

视图中定义的控件

<cntls:ItemSpecLookup ItemGUID="{Binding NewName,Mode=TwoWay}"
DataContext="{x:Bind ViewModel,Mode=TwoWay}"
AllowFocusOnInteraction="True"
Grid.Row="0"/>

用户控制

<UserControl
    x:Class="DesignTools.Controls.ItemSpecLookup"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:DesignTools.Controls"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:data="using:MIISiteDataModel.DataModels"
    xmlns:converters="using:DesignTools.Converters"
    mc:Ignorable="d"
    x:Name="root">

    <UserControl.Resources>
        <converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
        <converters:BooleanToInvertVisibilityConverter x:Key="BooleanToInvertVisibilityConverter"/>
        <converters:MoneyConverter x:Key="MoneyConverter"/>
    </UserControl.Resources>


    <StackPanel>


        <AutoSuggestBox x:Name="ASB"
                        QueryIcon="Find"

                        Margin="0,24,48,0"
                        PlaceholderText="Search for Item" 
                        TextMemberPath="ItemPartNumber"
                        QuerySubmitted="ItemSearchQuerySubmitted"
                        TextChanged="ItemSearchSearching"
                        SuggestionChosen="ItemSearchChosen">
        <AutoSuggestBox.ItemTemplate>

            <DataTemplate x:DataType="data:ItemSpecificationData">
                <UserControl>


                    <RelativePanel x:Name="rp" SizeChanged="rp_SizeChanged">

                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup>
                                <VisualState x:Name="DefaultState">
                                    <VisualState.StateTriggers>
                                        <AdaptiveTrigger MinWindowWidth="0"/>
                                    </VisualState.StateTriggers>
                                    <VisualState.Setters>
                                        <Setter Target="Cost.Opacity"  Value="0"/>
                                        <Setter Target="Description.Opacity" Value="0"/>
                                        <Setter Target="Model.Opacity" Value="0"/>
                                    </VisualState.Setters>
                                </VisualState>
                                <VisualState x:Name="Compact">
                                    <VisualState.StateTriggers>
                                        <AdaptiveTrigger MinWindowWidth="900"/>
                                    </VisualState.StateTriggers>
                                    <VisualState.Setters>
                                        <Setter Target="Cost.Opacity" Value="1"/>
                                        <Setter Target="Description.Opacity" Value="1"/>
                                        <Setter Target="Model.Opacity" Value="1"/>
                                    </VisualState.Setters>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>

                        <TextBlock x:Name="Make" 
                                   Text="{x:Bind ItemManufacturer,Mode=OneWay}"
                                   Style="{StaticResource SubtitleTextBlockStyle}"
                                   Foreground="{ThemeResource SystemControlForegroundAccentBrush}"/>

                        <TextBlock x:Name="Cost"
                                   Text="{x:Bind ItemCost,Mode=OneWay,Converter={StaticResource MoneyConverter}}"
                                   Style="{StaticResource BodyTextBlockStyle}"
                                   Foreground="{StaticResource MIIGreen}"
                                   Margin="0,2,0,0"
                                   Visibility="{x:Bind ItemDiscontinued,Mode=OneWay,Converter={StaticResource BooleanToVisibilityConverter}}"
                                   HorizontalTextAlignment="Left"
                                   RelativePanel.AlignRightWithPanel="True"
                                   RelativePanel.AlignTopWithPanel="True"/>

                        <TextBlock x:Name="Discontinued"
                                   Text="Discontinued"
                                   Style="{StaticResource BodyTextBlockStyle}"
                                   Foreground="{StaticResource MIIRed}"
                                   Margin="0,2,0,0"
                                   Visibility="{x:Bind ItemDiscontinued,Mode=OneWay,Converter={StaticResource BooleanToInvertVisibilityConverter}}"
                                   RelativePanel.AlignRightWithPanel="True"
                                   RelativePanel.AlignTopWithPanel="True"/>

                        <Image x:Name="IQIcon" 
                               Source="/Assets/IQCategories/Icon_Computers256.png" 
                               Stretch="UniformToFill" 
                               Margin="10,10,10,10"
                               Height="24" 
                               Width="24"
                               RelativePanel.Below="Make"/>

                        <TextBlock x:Name="Part" 
                                   Style="{StaticResource BodyTextBlockStyle}"
                                   Margin="4,2,0,0"
                                   RelativePanel.AlignTopWith="IQIcon"
                                   RelativePanel.RightOf="IQIcon">
                            <Run Text="Part: "/>
                            <Run Text="{x:Bind ItemPartNumber,Mode=OneWay}"/>
                        </TextBlock>

                        <TextBlock x:Name="Model" Style="{StaticResource BodyTextBlockStyle}"
                                   Foreground="{StaticResource MIIGray}"
                                   Margin="12,2,0,0"
                                   RelativePanel.AlignTopWith="Part"
                                   RelativePanel.RightOf="Part">
                            <Run Text="Model: "/>
                            <Run Text="{x:Bind ItemModel,Mode=OneWay}"/>
                        </TextBlock>

                        <TextBlock x:Name="Description"
                                   Text="{x:Bind ItemDescription,Mode=OneWay}"
                                   Style="{StaticResource CaptionTextBlockStyle}"
                                   Foreground="{StaticResource MIIGray}"
                                   TextWrapping="NoWrap"
                                   Margin="4,4,0,4"
                                   TextTrimming="CharacterEllipsis"
                                   RelativePanel.Below="Part"
                                   RelativePanel.RightOf="IQIcon"/>

                    </RelativePanel>

                </UserControl>
            </DataTemplate>



        </AutoSuggestBox.ItemTemplate>

    </AutoSuggestBox>

    </StackPanel>
</UserControl>

代码隐藏

    using DesignTools.ViewModels;
    using Microsoft.WindowsAzure.MobileServices;
    using MIISiteDataModel.Common;
    using MIISiteDataModel.DataModels;
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Diagnostics;
    using System.IO;
    using System.Linq;
    using System.Runtime.InteropServices.WindowsRuntime;
    using System.Threading.Tasks;
    using Windows.Foundation;
    using Windows.Foundation.Collections;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Controls.Primitives;
    using Windows.UI.Xaml.Data;
    using Windows.UI.Xaml.Input;
    using Windows.UI.Xaml.Media;
    using Windows.UI.Xaml.Navigation;

    // The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236

    namespace DesignTools.Controls
    {
        public sealed partial class ItemSpecLookup : UserControl
        {
            public ItemSpecLookup()
            {

            this.InitializeComponent();
            this.DataContext = this;
            //pull in mfg table?
            AzureService.ManufacturerTable.PullAsync(null,AzureService.ManufacturerTable.CreateQuery());
        }

        #region Dependencies

        public static readonly DependencyProperty itemGUID = DependencyProperty.Register("ItemGUID", typeof(string), typeof(ItemSpecLookup), new PropertyMetadata(null));

        public string ItemGUID
        {
            get { return (string)GetValue(itemGUID); }
            set { SetValue(itemGUID, value); }
        }

        #endregion

        #region Properties

        private ObservableCollection<ItemSpecificationData> _itemSearchList = new ObservableCollection<ItemSpecificationData>();
        public ObservableCollection<ItemSpecificationData> ItemSearchList
        {
            get { return _itemSearchList; }
            set {  _itemSearchList = value; }
        }

        #endregion

        public async void ItemSearchQuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
        {
            if (args.ChosenSuggestion != null)
            {
                ItemSpecificationData selectedItem = args.ChosenSuggestion as ItemSpecificationData;
                ItemGUID = selectedItem.Id;
            }
            else
            {
                ContentDialog invalidSite = new ContentDialog()
                {
                    Title = "Invalid Part Number",
                    Content = string.Format("'{0}' was not found in the database...", args.QueryText),
                    CloseButtonText = "Ok"
                };
                await invalidSite.ShowAsync();
            }
        }

        private async Task<string> IDtoMFG(string id)
        {
            ManufacturersData mfg = await AzureService.ManufacturerTable.LookupAsync(id);
            return mfg.Company;
        }

        public async void ItemSearchSearching(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
        {
            Debug.WriteLine("arg reason: " + args.Reason.ToString());
            switch (args.Reason)
            {
                case AutoSuggestionBoxTextChangeReason.ProgrammaticChange:
                    {
                        break;
                    }
                case AutoSuggestionBoxTextChangeReason.SuggestionChosen:
                    {
                        //IMobileServiceTable<ItemSpecificationData> OnlineItemList = AzureService.AzureClient.GetTable<ItemSpecificationData>();
                        //ASB.ItemsSource = await OnlineItemList.Where(i => i.Id == ItemGUID).ToCollectionAsync();
                        break;
                    }
                case AutoSuggestionBoxTextChangeReason.UserInput:
                    {
                        IMobileServiceTable<ItemSpecificationData> OnlineItemList = AzureService.AzureClient.GetTable<ItemSpecificationData>();
                        if (sender.Text != string.Empty)
                            //ItemSearchList = await OnlineItemList.Where(i => i.ItemPartNumber.Contains(sender.Text)).Take(25).OrderBy(i => i.ItemPartNumber).ToCollectionAsync();
                            ItemSearchList = await OnlineItemList.Select(i => new ItemSpecificationData { Id = i.Id, ItemManufacturer = i.ItemManufacturer, ItemPartNumber = i.ItemPartNumber, ItemModel = i.ItemModel, ItemDescription = i.ItemDescription, ItemCost = i.ItemCost, ItemDiscontinued = i.ItemDiscontinued }).Where(i => i.ItemPartNumber.Contains(sender.Text) || i.ItemModel.Contains(sender.Text)).Take(250).ToCollectionAsync();
                        else
                            //ItemSearchList = await OnlineItemList.Take(25).OrderByDescending(i => i.UpdatedAt).ToCollectionAsync();
                            ItemSearchList = await OnlineItemList.Select(i => new ItemSpecificationData { ItemManufacturer = i.ItemManufacturer, ItemPartNumber = i.ItemPartNumber, ItemModel = i.ItemModel, ItemDescription = i.ItemDescription, ItemCost = i.ItemCost, ItemDiscontinued = i.ItemDiscontinued }).Take(250).OrderByDescending(i => i.UpdatedAt).ToCollectionAsync();

                        foreach (ItemSpecificationData item in ItemSearchList)
                        {
                            item.ItemManufacturer = await IDtoMFG(item.ItemManufacturer);
                        }

                        ASB.ItemsSource = ItemSearchList.OrderBy(i => i.ItemManufacturer);
                        break;
                    }
            }
        }

        public void ItemSearchChosen(AutoSuggestBox sender, AutoSuggestBoxSuggestionChosenEventArgs args)
        {
            ItemSpecificationData test = args.SelectedItem as ItemSpecificationData;
        }

        private void rp_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            RelativePanel rp = sender as RelativePanel;
            rp.Width = ASB.ActualWidth - 24;
            //change visual states
        }
    }
}

Don't use: "this.DataContext = this"

我知道已经有一百万篇关于这个的帖子了,但我把它放在这里是为了让人们不要做我做的事哈哈