使用数据模板时的 wpf 绑定

发布于 2024-08-11 21:28:36 字数 1293 浏览 3 评论 0原文

好的,目前我有这段代码:

<TabItem Style="{DynamicResource MyStyle" x:Name="TabCustomers" Padding="0,1,4,1"
 Header={Binding Path=customersHeader}/>

现在我想在那里添加一个图标,所以我这样做(通过删除上面的标题):

<TabItem.Header>
<StackPanel Orientation="Horizontal">
     <Image Stretch="UniformToFill" Source="{StaticResource customers}"/>
     <TextBlock x:Key="textblock" Margin="4,0,0,0" 
     Text="{Binding Path=customersHeader}"/>
</StackPanel>
</TabItem.Header>

到目前为止还可以。 我想使用数据模板来概括这一点。我假设我必须在我的资源字典中执行此操作:

<DataTemplate x:Key="TabItemCustomersTemplate" DataType="{x:Type TabItem}">
<StackPanel Orientation="Horizontal">
     <Image Stretch="UniformToFill" Source="{StaticResource customers}"/>
     <TextBlock x:Key="textblock" Margin="4,0,0,0" 
     Text="{Binding Path=customersHeader}"/>
    </StackPanel>
</DataTemplate>

并在我的 tabitem 声明中更改此设置:

<TabItem ... HeaderTemplate="{StaticResource TabItemCustomersTemplate}".../>

所以我遇到了以下问题: 1)绑定不起作用,为什么? 2) 如何从 C# 访问文本块? 3)我如何概括这一点,这样我就不必为不同的选项卡项目(或其他控件)一遍又一遍地复制它,以便我每次都可以传递自己的文本和图像源?例如,您可以使用它来创建一个图像按钮,如果您有 20 个按钮,则代码会变得混乱。

有什么想法吗?

谢谢。

ok currently i have this piece of code:

<TabItem Style="{DynamicResource MyStyle" x:Name="TabCustomers" Padding="0,1,4,1"
 Header={Binding Path=customersHeader}/>

Now i want to add an icon there so I do (by removing the header above):

<TabItem.Header>
<StackPanel Orientation="Horizontal">
     <Image Stretch="UniformToFill" Source="{StaticResource customers}"/>
     <TextBlock x:Key="textblock" Margin="4,0,0,0" 
     Text="{Binding Path=customersHeader}"/>
</StackPanel>
</TabItem.Header>

So far it's ok.
I would like to generalize this using a datatemplate. I assume i have to do this in my resource dictionary:

<DataTemplate x:Key="TabItemCustomersTemplate" DataType="{x:Type TabItem}">
<StackPanel Orientation="Horizontal">
     <Image Stretch="UniformToFill" Source="{StaticResource customers}"/>
     <TextBlock x:Key="textblock" Margin="4,0,0,0" 
     Text="{Binding Path=customersHeader}"/>
    </StackPanel>
</DataTemplate>

and change this in my tabitem declaration:

<TabItem ... HeaderTemplate="{StaticResource TabItemCustomersTemplate}".../>

So i run into the following issues and questions:
1) binding doesnt work, why?
2) how can i access textblock from c#?
3) how can i generalize this so i dont have to copy this over and over again for different tab items (or other controls for the matter) so that i can pass my own text and image source each time? For example you might use this to create an image button and if you have 20 buttons the code becomes messy.

Any ideas?

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

清风不识月 2024-08-18 21:28:36
  1. 如果您将标题模板化
    tabitem,您不需要设置
    模板的数据类型。这
    header 是选项卡的属性
    item,它实际上是一个属性
    输入对象,你可以放入任何东西
    那里。

    尝试删除DataType="{x:Type
    TabItem}”
    并查看它是否有效。

  2. 您不需要访问
    来自 c# 的文本块,你应该制作
    与绑定系统有关。放置一个
    标头中的自定义对象。然后
    将此对象绑定到您的文本块
    然后调整对象,它会
    操纵文本块。到达
    一个元素总是困难的,如果它是
    包含在数据模板中。你
    应该不需要。如果你发现
    你自己沿着视觉树行走
    找到你正在做的视觉元素
    事情很困难,
  3. 你可以通过以下方式概括这一点
    建议2,使用自定义对象,
    删除数据的 x:Key
    模板并将其 DataType 设置为
    是您的自定义对象的类型。
    然后无论你的自定义对象在哪里
    看来你会得到它的数据
    正确模板化
  1. if you template the header in a
    tabitem, you do not need to set the
    data type of the template. the
    header is a property of the tab
    item, it is actually a property of
    type object, you can put anything in
    there.

    try removing the DataType="{x:Type
    TabItem}"
    and see if it works.

  2. you should not need to access the
    textblock from c#, you should make
    do with the binding system. place a
    custom object in your header. then
    bind this object to your textblock
    then adjust the object and it will
    manipulate the textblock. getting at
    an element is always hard if it is
    contained in a data template. you
    should not need to. if you find
    yourself walking the visual tree to
    find a visual element you are doing
    things the hard way
  3. you can generalise this by following
    suggestion 2, using a custom object,
    removing the x:Key of your data
    template and setting its DataType to
    be the type of your custom object.
    then wherever your custom object
    appears you will get it data
    templated properly
此刻的回忆 2024-08-18 21:28:36

面对我有用

<Window.Resources>
    <!-- <BitmapImage x:Key="customers" UriSource="einstein.jpg"/>--> 
    <DataTemplate x:Key="TabItemCustomersTemplate">
        <StackPanel Orientation="Horizontal">
            <Image Stretch="UniformToFill" Source="{Binding Path=Customers}"/>
            <TextBlock Margin="4,0,0,0" x:Name="txt" Text="{Binding Path=CustomersHeader}"/>
</StackPanel>
    </DataTemplate>
</Window.Resources>
    <Grid>
    <TabControl Name="mytabcontrol">
        <TabItem x:Name="TabCustomers" Padding="0,1,4,1" Header="{Binding}" HeaderTemplate="{StaticResource TabItemCustomersTemplate}">
            <Label Content="myContent" Background="Red"/>
        </TabItem>
    </TabControl>
</Grid>

试试这个,这在代码后

    public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();

        var lst = new List<People>();
        lst.Add(new People() { CustomersHeader = "My Customer" });
        this.DataContext = lst;
    }
}

public class People
{
    public string CustomersHeader { get; set; }
    public BitmapImage Customers { get; set; }
}

此外,您可以使用这个在代码后面找到您的文本块

TabPanel tabPanel = GetVisualChild<TabPanel>(mytabcontrol);
if (tabPanel != null)
{
    foreach (UIElement element in tabPanel.Children)
    {
        TabItem tabItem = element as TabItem;
        var image = FindNameFromHeaderTemplate<TextBlock>(tabItem, "txt");
    }
}

    public static T FindNameFromHeaderTemplate<T>(TabItem tabItem, String name) where T : UIElement
    {
        if (tabItem == null)
        {
            throw new ArgumentNullException("container");
        }

        if (tabItem.HeaderTemplate == null)
        {
            return null;
        }

        ContentPresenter contentPresenter = GetVisualChild<ContentPresenter>(tabItem);
        if (contentPresenter == null)
        {
            return null;
        }

        T element = tabItem.HeaderTemplate.FindName(name, contentPresenter) as T;
        return element;
    }

    public static T GetVisualChild<T>(Visual referenceVisual) where T : Visual
    {
        Visual child = null;
        for (Int32 i = 0; i < VisualTreeHelper.GetChildrenCount(referenceVisual); i++)
        {
            child = VisualTreeHelper.GetChild(referenceVisual, i) as Visual;
            if (child != null && child.GetType() == typeof(T))
            {
                break;
            }
            else if (child != null)
            {
                child = GetVisualChild<T>(child);
                if (child != null && child.GetType() == typeof(T))
                {
                    break;
                }
            }
        }
        return child as T;
    }

Try this, This is working for me

<Window.Resources>
    <!-- <BitmapImage x:Key="customers" UriSource="einstein.jpg"/>--> 
    <DataTemplate x:Key="TabItemCustomersTemplate">
        <StackPanel Orientation="Horizontal">
            <Image Stretch="UniformToFill" Source="{Binding Path=Customers}"/>
            <TextBlock Margin="4,0,0,0" x:Name="txt" Text="{Binding Path=CustomersHeader}"/>
</StackPanel>
    </DataTemplate>
</Window.Resources>
    <Grid>
    <TabControl Name="mytabcontrol">
        <TabItem x:Name="TabCustomers" Padding="0,1,4,1" Header="{Binding}" HeaderTemplate="{StaticResource TabItemCustomersTemplate}">
            <Label Content="myContent" Background="Red"/>
        </TabItem>
    </TabControl>
</Grid>

in code behind

    public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();

        var lst = new List<People>();
        lst.Add(new People() { CustomersHeader = "My Customer" });
        this.DataContext = lst;
    }
}

public class People
{
    public string CustomersHeader { get; set; }
    public BitmapImage Customers { get; set; }
}

Further you can find your textblock in code behind using this

TabPanel tabPanel = GetVisualChild<TabPanel>(mytabcontrol);
if (tabPanel != null)
{
    foreach (UIElement element in tabPanel.Children)
    {
        TabItem tabItem = element as TabItem;
        var image = FindNameFromHeaderTemplate<TextBlock>(tabItem, "txt");
    }
}

    public static T FindNameFromHeaderTemplate<T>(TabItem tabItem, String name) where T : UIElement
    {
        if (tabItem == null)
        {
            throw new ArgumentNullException("container");
        }

        if (tabItem.HeaderTemplate == null)
        {
            return null;
        }

        ContentPresenter contentPresenter = GetVisualChild<ContentPresenter>(tabItem);
        if (contentPresenter == null)
        {
            return null;
        }

        T element = tabItem.HeaderTemplate.FindName(name, contentPresenter) as T;
        return element;
    }

    public static T GetVisualChild<T>(Visual referenceVisual) where T : Visual
    {
        Visual child = null;
        for (Int32 i = 0; i < VisualTreeHelper.GetChildrenCount(referenceVisual); i++)
        {
            child = VisualTreeHelper.GetChild(referenceVisual, i) as Visual;
            if (child != null && child.GetType() == typeof(T))
            {
                break;
            }
            else if (child != null)
            {
                child = GetVisualChild<T>(child);
                if (child != null && child.GetType() == typeof(T))
                {
                    break;
                }
            }
        }
        return child as T;
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文