WPF绑定用户控件
本文关键字:控件 用户 绑定 WPF | 更新日期: 2023-09-27 17:49:42
我一直在寻找解决这个问题的方法。我有一个标签适配器类,我用它来填充标签控件
public partial class TabAdapter : UserControl
{
public static readonly DependencyProperty fileNameProperty =
DependencyProperty.Register(
"fileName",
typeof(string),
typeof(TabAdapter),
new FrameworkPropertyMetadata(
string.Empty,
FrameworkPropertyMetadataOptions.AffectsRender,
new PropertyChangedCallback(OnFileNamePropertyChanged),
new CoerceValueCallback(coerceFileName)
),
new ValidateValueCallback(fileNameValidationCallback)
);
public TabAdapter()
{
InitializeComponent();
//initializeInterior();
CreateSaveCommand();
TabAdapterContent.DataContext = this;
Console.WriteLine("constructor hit.");
}
public string fileName
{
get { return (string)GetValue(fileNameProperty); }
set { SetValue(fileNameProperty, value); }
}
private ColumnMapper _columnMap;
private TableMapper _tableMap;
private TabType tabType;
private enum TabType { TABLE_MAPPER, COLUMN_MAPPER, ERROR_MSG }
private static object coerceFileName(DependencyObject d, object value)
{
return fileName;
}
private static bool fileNameValidationCallback(object Value)
{
string fn = (string)Value;
if (fn.Equals(string.Empty))
{
return true;
}
FileInfo fi = new FileInfo(fn);
return ((fi.Exists && fi.Extension.Equals(".csv")));
}
private static void OnFileNamePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs args)
{
TabAdapter source = d as TabAdapter;
Console.WriteLine("got to property changer: " + (string)args.NewValue + " :new / old: " + (string)args.OldValue);
source.initializeInterior();
}
private void initializeInterior()
{
Console.WriteLine("initializing Interior filename: " + fileName);
if (Regex.IsMatch(fileName, @".*_SourceTableMapping.csv$"))
{
tabType = TabType.TABLE_MAPPER;
_tableMap = new TableMapper(fileName);
Grid.SetRow(_tableMap, 0);
Grid.SetColumn(_tableMap, 0);
//clear out the content.
this.TabAdapterContent.Children.Clear();
//add new content
this.TabAdapterContent.Children.Add(_tableMap);
}
else if (fileName.EndsWith(".csv"))
{
tabType = TabType.TABLE_MAPPER;
_columnMap = new ColumnMapper(fileName);
Grid.SetRow(_columnMap, 0);
Grid.SetColumn(_columnMap, 0);
//clear out the content.
this.TabAdapterContent.Children.Clear();
//add new content
this.TabAdapterContent.Children.Add(_columnMap);
}
else
{
tabType = TabType.ERROR_MSG;
TextBlock tb = new TextBlock();
tb.Text = "The File: " + fileName + " is not a valid mapping file.";
Grid.SetRow(tb, 0);
Grid.SetColumn(tb, 0);
//clear out the content.
this.TabAdapterContent.Children.Clear();
//add new content
this.TabAdapterContent.Children.Add(tb);
}
}
}
这样做的目的是决定要添加什么类型的文件,并在其中加载正确的用户控件以显示该文件。
TAB控件的主窗口xaml是
<TabControl x:Name="tabControl" Grid.Column="1" Grid.Row="0" ItemsSource="{Binding openFileNames, Mode=OneWay}">
<TabControl.LayoutTransform>
<!-- Allows to zoom the control's content using the slider -->
<ScaleTransform CenterX="0"
CenterY="0" />
<!-- part of scale transform ScaleX="{Binding ElementName=uiScaleSlider,Path=Value}"
ScaleY="{Binding ElementName=uiScaleSlider,Path=Value}" />-->
</TabControl.LayoutTransform>
<!-- Header -->
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Header}" />
</DataTemplate>
</TabControl.ItemTemplate>
<!-- Content -->
<TabControl.ContentTemplate>
<DataTemplate>
<local:TabAdapter fileName="{Binding fileName}" />
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
头可以工作,如果我改变
<local:TabAdapter fileName="{Binding fileName}" />
到
<TextBlock Text="{Binding fileName}" />
然后它都正确绑定,我有一种感觉,它与我的选项卡适配器上的数据上下文有关。但不确定需要设置成什么
TAB适配器的xaml是
<UserControl x:Class="ImportMappingGui.TabAdapter"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid x:Name="TabAdapterContent">
<Grid.RowDefinitions>
<RowDefinition Height = "*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
</Grid>
将全部编译并运行,但只有用户控件的构造函数被击中,而且无论我创建了多少制表符,都只击中一次。这是我的第一个WPF应用程序,所以我的道歉,如果它是愚蠢的东西我错过了。(或者如果我设置各种适配器的方法不是解决此问题的最佳方法)。
不要从UserControl本身设置UserControl
的DataContext
。它破坏了"不好看"控件的全部意义,这些控件可以用来显示你传递给它的任何东西。
您的fileName
绑定失败,因为DataContext = this
和this
是TabAdapter
控件本身,而TabAdapter.fileName
实际上没有设置为任何东西。(请记住,绑定告诉属性在其他地方检索它的值与直接设置值是不同的)
对于不运行一次以上的构造函数,这是设计的。由于您告诉TabControl使用TabAdapter
控件作为模板,因此它将创建TabAdapter
的一个副本,并在切换选项卡时简单地替换控件后面的.DataContext
。这提高了性能,因为它不必为每个选项卡保持初始化和跟踪单独的控件,并减少了内存的使用。