C# 从WPF中的主窗口引发用户控件上的事件

C# 从WPF中的主窗口引发用户控件上的事件,c#,wpf,xaml,event-handling,C#,Wpf,Xaml,Event Handling,在我的mainwindow.xaml中有一个文本框,当我输入文本框时,我希望usercontrol中的标签,即View1.xaml会相应地更新。然而,当我输入文本框时,我意识到事件根本不是在用户控件中引发的,你能告诉我哪个部分是错误的吗 事件可以在文本框中引发\u TextChanged\u 1 我的主窗口.XAML <Window xmlns:my="http://schemas.microsoft.com/winfx/2006/xaml/presentation/ribbon"

在我的mainwindow.xaml中有一个文本框,当我输入文本框时,我希望usercontrol中的标签,即View1.xaml会相应地更新。然而,当我输入文本框时,我意识到事件根本不是在用户控件中引发的,你能告诉我哪个部分是错误的吗

事件可以在文本框中引发\u TextChanged\u 1

我的主窗口.XAML

<Window xmlns:my="http://schemas.microsoft.com/winfx/2006/xaml/presentation/ribbon"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:testapplication"  x:Class="testapplication.MainWindow"
        Title="MainWindow" Height="964" Width="790">
    <Grid >
        <Button x:Name="OpenView1" Content="Open Window 1" HorizontalAlignment="Left" Margin="33,70,0,0" VerticalAlignment="Top" Width="111" RenderTransformOrigin="0.279,1.409" Click="OpenView1_Click"/>
        <Button x:Name="OpenView2" Content="Open Window 2" HorizontalAlignment="Left" Margin="33,169,0,0" VerticalAlignment="Top" Width="111" Click="OpenView2_Click"/>
        <Button x:Name="OpenView3" Content="Open Window 3" HorizontalAlignment="Left" Margin="33,259,0,0" VerticalAlignment="Top" Width="111" Click="OpenView3_Click"/>

        <local:View1 x:Name="ViewOne" HorizontalAlignment="Left" Margin="33,332,0,0" VerticalAlignment="Top" Height="226" Width="204"  Visibility="Hidden"/>
        <local:View2 x:Name="ViewTwo" HorizontalAlignment="Left" Margin="284,332,0,0" VerticalAlignment="Top" Height="226" Width="208" Visibility="Hidden"/>
        <local:View3 x:Name="ViewThree" HorizontalAlignment="Left" Margin="534,332,0,0" VerticalAlignment="Top" Height="226" Width="196" Visibility="Hidden"/>
        <TextBox HorizontalAlignment="Left" Height="42" Margin="326,70,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="182" FontSize="22" TextChanged="TextBox_TextChanged_1"/>

    </Grid>
</Window>

我的MainWindow.cs

namespace testapplication
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
           //InitializeComponent();
        }

        //event handler
        public event EventHandler<EventArgs> changedText;

        private void OpenView1_Click(object sender, RoutedEventArgs e)
        {
            ViewOne.Visibility = Visibility.Visible;
        }

        private void OpenView2_Click(object sender, RoutedEventArgs e)
        {
            ViewTwo.Visibility = Visibility.Visible;
        }

        private void OpenView3_Click(object sender, RoutedEventArgs e)
        {
            ViewThree.Visibility = Visibility.Visible;
        }

        private void TextBox_TextChanged_1(object sender, TextChangedEventArgs e)
        {

            if (changedText != null)
            {
               changedText(this, e);
            }
        }


    }
}
命名空间测试应用程序
{
/// 
///MainWindow.xaml的交互逻辑
/// 
公共部分类主窗口:窗口
{
公共主窗口()
{
//初始化组件();
}
//事件处理程序
公共事件事件处理程序changedText;
私有void OpenView1_单击(对象发送者、路由目标)
{
ViewOne.Visibility=可见性.Visibility;
}
私有void openview 2_单击(对象发送方,路由目标)
{
ViewTwo.Visibility=可见性.Visibility;
}
私有void openview 3_单击(对象发送方,路由目标)
{
ViewThree.Visibility=可见性.Visibility;
}
私有无效文本框\u TextChanged\u 1(对象发送者,textchangedventargs e)
{
if(changedText!=null)
{
更改文本(本,e);
}
}
}
}
这是我的用户控件,称为View1.xaml,它包含在我的MainWindow.xaml中

namespace testapplication
{
    /// <summary>
    /// Interaction logic for View1.xaml
    /// </summary>
    public partial class View1 : UserControl
    {

        private MainWindow newWindow = new MainWindow();
        public View1()
        {
            InitializeComponent();

            newWindow.changedText += newWindow_ChangeText;
        }

        void newWindow_ChangeText(object sender, EventArgs e)
        {
            ViewOnelabel.Content = "Happy";
        }




    }
}
命名空间测试应用程序
{
/// 
///View1.xaml的交互逻辑
/// 
公共部分类View1:UserControl
{
私有主窗口newWindow=新主窗口();
公众意见1()
{
初始化组件();
newWindow.changedText+=newWindow\u ChangeText;
}
void newWindow_ChangeText(对象发送方,事件参数e)
{
ViewOnelabel.Content=“快乐”;
}
}
}

问题是myViewOnelabel.Content=“Happy”根本没有执行,它保持不变

这里的主要问题是,View1类订阅的是新MainWindow实例上的事件,而不是应用程序启动时创建的MainWindow实例。 由于MainWindow类引用了View1类(命名成员“ViewOne”),因此只需从MainWindow类更改它即可

private void TextBox_TextChanged_1(object sender, TextChangedEventArgs e)
        {

            ViewOne.ViewOneLabel.Content = "Happy";
        }
去掉chenagedText事件处理程序和View1.xaml.cs中的所有代码。。。你不需要它


注意:我希望你只是在这里玩和学习。。。我决不会容忍以这种方式构建WPF应用程序。

您只能使用主页的事件。我建议您向UserControl添加一个属性。就我而言,我称之为文本

public string Text
{
    set { ViewOneLabel.Content = value; }
}
在主窗口中,使用TextChanged事件中的属性

private void TextBox_TextChanged_1(object sender, TextChangedEventArgs e)
{
    OpenView1.Text = TextBox.Text;
}

有几件事我想指出

wpf中winforms标签的等价物是TextBlock。wpf标签实际上是contentcontrol的一种类型。因此,内容属性

在wpf中有路由事件。这些“气泡”向上(向下)可视化树。这意味着您可以从窗口内usercontrol中的控件处理窗口中的事件

但主要是。 我鼓励您研究MVVM模式。 我已经编写了一些代码来说明这些要点。 不过我建议只使用绑定和mvvm

我的主窗口标记: Title=“MainWindow”Height=“350”Width=“525”

在处理程序中,您不会对文本框中的文本执行任何操作,但我有一些代码证明,如果您需要,可以从mainwindow获取这些文本

我的viewmodel: 公共类MainWindowViewModel:INotifyPropertyChanged { 私有字符串输入字符串

    public string InputString
    {
        get { return inputString; }
        set
        {
            inputString = value;
            OutputString = $"{inputString.Length} characters entered";
            RaisePropertyChanged();
        }
    }

    private string outputString;

    public string OutputString
    {
        get { return outputString; }
        set
        {
            outputString = value;
            RaisePropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void RaisePropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
Usercontrol1只有一个文本框:

<Grid>
    <TextBox Text="{Binding InputString, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>

在该文本框中键入时,文本将传输到我的viewmodel中的绑定属性。这将命中我的setter中的代码。这反过来设置绑定到我的文本块的OutputString

键入时,标签和文本块中的文本都会发生更改

这是我在onedrive上的示例链接

您正在
UserControl
中创建
MainWindow
的新实例。您要做的是将事件处理程序连接到您在屏幕上实际看到的实例。您可以使用
窗口获取对此实例的引用。GetWindow
方法:

public partial class View1 : UserControl
{
    public View1()
    {
        InitializeComponent();

        Loaded += (s, e) => 
        {
            Window mainWindow = Window.GetWindow(this) as MainWindow;
            if(mainWindow != null)
                mainWindow.changedText += newWindow_ChangeText;
        };
    }

    void newWindow_ChangeText(object sender, EventArgs e)
    {
        ViewOnelabel.Content = "Happy";
    }
}

我还在学习,我希望用eventhandler的方式构建一个应用程序,我能在view1上做些什么来让它工作吗?@user2399158这是一个相当复杂但很好的方法,可以将MVVM与WPF和导航一起使用,你似乎在追求这一点。使用MVVM。这可以通过绑定轻松完成。我怎么做?你能给我举个例子吗?JusDon’不要去youtube搜索WPF和MVVM。将会有大量的初学者教程。我真的建议你这样做。这会让你的生活更轻松。实际上不需要视图模型。UserControl应该只公开一个依赖项属性,它可以绑定到TextBox的文本属性。在UserControl的XAML中,你可以绑定它ViewOnelabel的内容通过RelativeSource绑定到UserControl dependency属性。@Fildor当然,重要的一点是可绑定的dependency属性,它可以绑定到视图模型以及其他元素的属性。
<Grid>
    <TextBox Text="{Binding InputString, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
public partial class View1 : UserControl
{
    public View1()
    {
        InitializeComponent();

        Loaded += (s, e) => 
        {
            Window mainWindow = Window.GetWindow(this) as MainWindow;
            if(mainWindow != null)
                mainWindow.changedText += newWindow_ChangeText;
        };
    }

    void newWindow_ChangeText(object sender, EventArgs e)
    {
        ViewOnelabel.Content = "Happy";
    }
}