XAML 从WPF的主窗口在User控件上引发事件

xwmevbvl  于 2023-04-27  发布在  其他
关注(0)|答案(4)|浏览(116)

在我的主窗口中有一个文本框,当我进入文本框时,我希望我的用户控件中的标签,称为View1.xaml将相应地更新。然而,我意识到当我输入文本框时,用户控件中的事件根本没有引发,你能告诉我哪一部分是错误的吗?

TextBox_TextChanged_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);
            }
        }

    }
}

这是我的UserControl,称为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";
        }



    }
}

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

xmd2e60i

xmd2e60i1#

有几件事我想指出。
wpf中与winforms标签等价的是TextBlock。wpf标签实际上是contentcontrol的一种类型。因此有了content属性。
在wpf中有路由事件。这些事件在可视树中向上“冒泡”(并向下隧道)。这意味着你可以从窗口中的用户控件中的控件处理窗口中的事件。
但主要是。我鼓励你研究MVVM模式。我已经把一些代码放在一起说明了这些点。我建议只使用绑定和mvvm。
我的主窗口标记:

<Window
    Title="MainWindow" Height="350" Width="525"
    
    TextBoxBase.TextChanged="Window_TextChanged"
    
    <Window.DataContext>
    <local:MainWindowViewModel/>
    </Window.DataContext>
    <Grid>
        <StackPanel>
            <Label Name="OutputLabel"/>
            <TextBlock Text="{Binding OutputString}"/>
            <local:UserControl1/>
        </StackPanel>
    
    </Grid>
</Window>

请注意,它处理的是一个textchanged事件,因为它是在路由,所以它将从其中的UserControl1获取事件。

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void Window_TextChanged(object sender, TextChangedEventArgs e)
    {
        OutputLabel.Content = $"Happy {((TextBox)e.OriginalSource).Text}";
    }
}

你不需要在处理程序中对文本框中的文本做任何处理,但是我有一些代码可以证明,如果你愿意的话,你可以从主窗口中得到它。
我的视图模型:

public class MainWindowViewModel : INotifyPropertyChanged
{
    private string inputString;

    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中的代码。这反过来会设置绑定到我的textblock的OutputString。
当我键入时,标签和文本块中的文本都会发生变化。
这是我在onedrive https://1drv.ms/u/s!AmPvL3r385QhgpgOPNKPs-veFJ2O3g上的示例链接

bqujaahr

bqujaahr2#

这里的主要问题是,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应用程序。

zsbz8rwp

zsbz8rwp3#

你只能使用MainPage的事件。我建议你在UserControl中添加一个属性。在我的例子中,我称之为Text。

public string Text
{
    set { ViewOneLabel.Content = value; }
}

在主窗口中,使用TextChanged事件中的属性。

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

emeijp434#

你正在UserControl中创建一个MainWindow的新示例。你要做的是将一个事件处理程序挂接到你在屏幕上实际看到的示例上。你可以使用Window.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";
    }
}

相关问题