【问题标题】:Making a button content change within user control on click单击时在用户控件中更改按钮内容
【发布时间】:2019-10-13 11:12:26
【问题描述】:

我意识到 WPF 对我来说仍然是一种魔法。问题似乎很简单。我有一个带有按钮的用户控件。我想在点击时更改按钮内容(文本)。

如果我在没有初始化按钮值的情况下使用用户控件打开表单,然后在

void Button_Click(object sender, RoutedEventArgs e) 
{ 
    Button.Content = "New Value"; 
}

它有效。

如果我在控件构造函数中通过Button.Content = "Init Value"动态初始化按钮值,第二位Button.Content = "New Value" 永远不会发生(它会发生,但按钮文本不会再显示更改,至少看起来是这样)。

所以我决定使用绑定。在 MyUserControl 中声明 ButtonText 属性(+ 带有 getter 和 setter 的相应 DependencyProperty)并尝试在构造函数中执行 ButtonText = "Init Value"; 并在 Button_Click() 中执行 ButtonText = "New Value";。第一个有效,第二个仍然无效。我假设是因为Button_Click() 中的数据上下文错误?

在 MyUserControl 中我尝试了一些方法,包括

<Button x:Name="Button" 
 Content="{Binding Path=ButtonText, RelativeSource={RelativeSource AncestorType=UserControl}}"
 Click="Button_Click" />

<Button x:Name="Button"
 Content="{Binding Path=ButtonText, Element=MyUserControl}" 
 Click="Button_Click" />

似乎没有任何效果。

实现我需要的最简单方法是什么,即动态初始化和动态更改?如果可能的话,请解释一下为什么我的第一种(直接)方法不起作用以及缺少什么绑定方法。

非常感谢!

编辑:

另一种方法是使用触发器。

这个例子有效:

<Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
    <Setter Property="Content" Value="Init Value"/>
    <Style.Triggers>
        <Trigger Property="IsClicked" Value="True">
            <Setter Property="Content" Value="New Value" />
        </Trigger>
    </Style.Triggers>
</Style>

我的问题是我需要一个 DataTrigger,像这样

<Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
    <Setter Property="Content" Value="Init Value"/>
    <Style.Triggers>
        <DataTrigger Binding="{Binding Path=MyUserControlProperty, ElementName=MyUserControl}" Value="True">
            <Setter Property="Content" Value="New Value" />
        </DataTrigger>
    </Style.Triggers>
</Style>

如何使 MyUserControlProperty 值更改正确传播?

最有趣的是,如果我以新形式打开控件,Button.Content = "Init Value" 的初始化不会搞砸一切,一切正常。什么?为什么这个简单的任务这么难,为什么会有这么多行为?

【问题讨论】:

  • 如果不查看 UserControl 的所有相关代码部分,很难判断哪里出错了。您可能混淆了 UserControl 中的元素名称。当您像这样编写它时,通过单击处理程序总是更改按钮的内容:((Button)sender).Content = "New Value";

标签: wpf button user-controls


【解决方案1】:

当您设置了绑定时,不要直接设置 Button.Content。如果您在构造函数中设置 Button.Content ,您将有效地删除绑定。 这有效:

<Window x:Class="StackOverflow.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="450" Width="800">
    <StackPanel>
        <Button Content="{Binding Path=ButtonText1, RelativeSource={RelativeSource AncestorType=Window}}"  Click="Button1_OnClick"></Button>
    </StackPanel>
</Window>

using System.Windows;

namespace StackOverflow
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow
    {
        public MainWindow()
        {
            InitializeComponent();
            ButtonText1 = "Paul";
        }

        private void Button1_OnClick(object sender, RoutedEventArgs e)
        {
            ButtonText1 = "Maria";
        }

        public string ButtonText1
        {
            get => (string)GetValue(ButtonText1Property);
            set => SetValue(ButtonText1Property, value);
        }

        // Using a DependencyProperty as the backing store for ButtonText1.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ButtonText1Property =
            DependencyProperty.Register("ButtonText1", typeof(string), typeof(MainWindow), new PropertyMetadata("Peter"));


    }
}

【讨论】:

  • 这没有回答问题。直接设置Button的Content是完全有效的。
  • Clemens 当然是对的。我的第一个答案太简陋了...
  • 你现在拥有的显然也有效。但是,根据 OP 在他们的问题中所写的内容,这正是他们所尝试的。根据问题,他们也建立了Binding时没有直接设置Content。这只是两个不同的试验。正如我在对该问题的评论中指出的那样,如果不查看更多详细信息,就无法回答。
  • 再次编辑...无论如何OP在构造函数中直接设置Button.Content。这杀死了绑定。
  • OP 清楚地写道,当没有绑定时,他们尝试直接设置内容失败。有了Binding,他们并没有直接设置Content,而是源属性(ButtonText = "New Value";)。您不应该拼命尝试回答当前无法回答的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-10
  • 1970-01-01
相关资源
最近更新 更多