我在ContentControl的XAML表单上创建了一个文本块。当我尝试对其进行编程时,C#无法识别该名称,并且对此也无能为力。
我尝试将文本块添加到内容控件之外的表单中,但这仍然不能解决问题。
这是XAML代码:
<ContentControl>
<ContentControl.Template>
<ControlTemplate>
<Grid VerticalAlignment="Bottom" Height="250" Margin="0,450,0,0">
<Rectangle Fill="Beige" Stroke="Black" StrokeThickness="3"
Width="639" Height="250" Margin="0,0,0,0"/>
<TextBlock Text="Goal:" FontSize="18" Margin="7,50,0,0"/>
<TextBlock Text="Eaten:" FontSize="18" Margin="7,120,0,0"/>
<TextBlock Text="Remaining:" FontSize="18" Margin="7,190,0,0"/>
<TextBlock Text="Calories:" FontSize="18" Margin="140,10,0,0"/>
<TextBlock Text="Fat(g):" FontSize="18" Margin="270,10,0,0"/>
<TextBlock Text="Carbs(g):" FontSize="18" Margin="380,10,0,0"/>
<TextBlock Text="Protein(g):" FontSize="18" Margin="520,10,0,0"/>
<TextBlock x:Name="lblCalorieGoal" Text="Peb"
TextAlignment="Center" FontSize="18" Margin="-290,50,0,0"/>
</Grid>
</ControlTemplate>
</ContentControl.Template>
<TextBlock Text="TextBlock" TextWrapping="Wrap"/>
</ContentControl>
然后是相应的工作C#代码:
public LogFood()
{
this.InitializeComponent();
Windows.Storage.ApplicationDataContainer localSettings =
Windows.Storage.ApplicationData.Current.LocalSettings;
Windows.Storage.StorageFolder localFolder =
Windows.Storage.ApplicationData.Current.LocalFolder;
Windows.Storage.ApplicationDataCompositeValue composite =
(Windows.Storage.ApplicationDataCompositeValue)localSettings
.Values["nutritionSettings"];
int calorieMin = Convert.ToInt32(composite["calorieMin"]);
int calorieMax = Convert.ToInt32(composite["calorieMax"]);
int gramsFatMin = Convert.ToInt32(composite["gramsFatMin"]);
int gramsFatMax = Convert.ToInt32(composite["gramsFatMax"]);
int gramsCarbsMin = Convert.ToInt32(composite["gramsCarbsMin"]);
int gramsCarbsMax = Convert.ToInt32(composite["gramsCarbsMax"]);
int gramsProteinMin = Convert.ToInt32(composite["gramsProteinMin"]);
int gramsProteinMax = Convert.ToInt32(composite["gramsProteinMax"]);
lblCalorieGoal.Text = calorieMin;
}
我希望能够更改文本块的文本。而是出现错误“名称lblCalorieGoal.Text在当前上下文中不存在。”
答案 0 :(得分:1)
此处的关键实现是模板可能是XAML的可重用部分,因此实际上其中的任何内容都嵌入了其中,而不是“可公开访问的”,因为在视图上可能存在同一模板的多个实例。
话虽如此,您仍然可以通过使用VisualTreeHelper
-
internal static FrameworkElement FindChildByName(DependencyObject startNode, string name)
{
int count = VisualTreeHelper.GetChildrenCount(startNode);
for (int i = 0; i < count; i++)
{
DependencyObject current = VisualTreeHelper.GetChild(startNode, i);
if (current is FrameworkElement frameworkElement)
{
if (frameworkElement.Name == name)
return frameworkElement;
}
var result = FindChildByName(current, name);
if ( result != null)
{
return result;
}
}
return null;
}
请注意,此操作仅在加载控件后有效(例如,在Page.Loaded
事件处理程序-
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
var block = FindChildByName(ContentRoot, "lblCalorieGoal") as TextBlock;
}
但是,这都不是解决您问题的理想解决方案。相反,您应该完全放弃使用ContentControl
,并将控件直接放在页面上的模板中(这将使它们可以直接从后面的代码中直接访问),或/和/或使用数据绑定来绑定数据直接转到适当的控件。在这种情况下,我将创建一个类来保存数据,例如:
public class NutritionInfo
{
public string CalorieGoal { get; set; }
}
现在而不是ContentControl.ControlTemplate
(它将替换整个控件的模板),您将替换ContentTemplate
(实际上是ControlTemplate实际上显示的东西):
<ContentControl x:Name="ContentRoot">
<ContentControl.ContentTemplate>
<DataTemplate x:DataType="local:NutritionInfo">
... your template
</DataTemplate>
</ContentControl.ContentTemplate>
</ContentControl>
请注意,我们使用x:DataType
来指定绑定到的类型,以便我们可以使用x:Bind
语法。最后,我们更新模板本身:
<TextBlock x:Name="lblCalorieGoal" Text="{x:Bind CalorieGoal}" ... />
我们使用x:Bind
将TextBlock
的文本绑定到CalorieGoal
属性。我们差不多完成了,现在只需将Content
的{{1}}属性设置为ContentControl
的实例(例如,通过数据绑定或直接):
NutritionInfo
总体而言,我建议进一步阅读XAML中数据绑定的工作原理,因为这将帮助您显着简化代码,避免直接通过ContentRoot.Content = new NutritionInfo()
{
CalorieGoal = "1243"
};
访问控件,并使UI与代码脱钩。有关更多信息,请参见documentation。