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"
我知道已经有一百万篇关于这个的帖子了,但我把它放在这里是为了让人们不要做我做的事哈哈
每次我创建一个 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"
我知道已经有一百万篇关于这个的帖子了,但我把它放在这里是为了让人们不要做我做的事哈哈