0

I have a usercontrol where the xaml is as follows. Please see the VisualChild line in the cs file thats the problem. When I try to find the UserControl I keep a break point it is null and hence I cant find the textblock element. My VisualChild is the same code at this place. How can I find WPF controls by name or type? Please help.

XAML:

<UserControl Name="NFView" x:Class="AthenaIsolatedFeatures.ProximityAlerts.Views.NotificationView"
             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" 
             xmlns:local="clr-namespace:AthenaIsolatedFeatures.ProximityAlerts.Views"
             xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
             xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <UserControl.Resources>
        <DataTemplate x:Key="CustomNotificationTemplate">

            <Border Name="border" BorderBrush="Black" BorderThickness="1" MouseLeftButtonDown="Border_MouseLeftButtonDown">
                <!--<i:Interaction.Triggers>
                    <i:EventTrigger EventName="MouseDown">
                        <i:InvokeCommandAction Command="{Binding AlertClickCommand}" CommandParameter="{Binding}"></i:InvokeCommandAction>
                    </i:EventTrigger>
                </i:Interaction.Triggers>-->

                <DockPanel LastChildFill="True">

                    <StackPanel DockPanel.Dock="Top" Grid.Row="0" Background="Red">
                        <TextBlock Text="Proximity Alert" HorizontalAlignment="Left"></TextBlock>
                    </StackPanel>
                    <Grid Name="GRD2" Background="#FFB6C1" DockPanel.Dock="Bottom" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">

                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"></RowDefinition>
                            <!--<RowDefinition Height="Auto"></RowDefinition>-->
                            <RowDefinition Height="Auto"></RowDefinition>
                            <RowDefinition Height="Auto"></RowDefinition>

                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto"></ColumnDefinition>
                            <ColumnDefinition Width="Auto"></ColumnDefinition>
                            <ColumnDefinition Width="Auto"></ColumnDefinition>

                        </Grid.ColumnDefinitions>

                        <Image Source="{Binding Source}" Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" Margin="4,-25,0,0" Height="100" Width="65"></Image>

                        <TextBlock Grid.Row="0" Margin="25,5,0,0" Grid.Column="1" Text="{Binding AlertDescription}" FontSize="15" FontWeight="Bold"></TextBlock>
                        <!--<TextBlock Grid.Row="1" Grid.Column="1" Margin="7,1,0,0" Text="{Binding requestId}"></TextBlock>-->
                        <TextBlock Grid.Row="1" Margin="25,-28,0,0" Grid.Column="1" Text="{Binding requestId,StringFormat='Session: {0}'}"></TextBlock>
                        <TextBlock Grid.Row="0" Grid.Column="2" HorizontalAlignment="Right" Margin="39,5,0,0" Text="{Binding alertTimeStamp}"></TextBlock>
                        <TextBlock Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" Margin="25,-30,0,0" Text="{Binding AlertText}"></TextBlock>
                        <TextBlock Name="tblAlertId" Grid.Row="2" Grid.Column="1" Text="{Binding alertId}" Visibility="Collapsed"></TextBlock>
                    </Grid>
                </DockPanel>
            </Border>
        </DataTemplate>
    </UserControl.Resources>
    <Grid>

    </Grid>
</UserControl>

The code behind I have

 public partial class NotificationView : UserControl
    {
        public int alertId { get; set; }

        public NotificationView()
        {
            InitializeComponent();
        }

        private void Border_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {

            var item = FindVisualChild.FindChild<TextBlock>(NFView, "tblAlertId"); //Problem is this line.
            alertId = Convert.ToInt32(item.Text);
            executeAlertClickCommand(ConsoleSettingsModel.GetInstance().SettingsCommandsData.AlertCommand, alertId);
        }

        internal void executeAlertClickCommand(WSMgrCommands cmd, int id) //Raising custom command
        {
            var wsParams = new WSAcknoledgedAlert();
            wsParams.alertId = id;
            if (cmd.CanExecute(wsParams))
            {
                cmd.Execute(wsParams);
            }
        }


    }
Community
  • 1
  • 1
nikhil
  • 1,578
  • 3
  • 23
  • 52

3 Answers3

0

Where are you using this datatemplate in?? Is it in a listbox?? You should be able to access your control using the FrameworkTemplate.FindName method. First, get the ContentPresenter from one of the ListBoxItems:

ContentPresenter contentPresenter = FindVisualChild<ContentPresenter>(yourListBoxItemName);

Then get the DataTemplate from the ContentPresenter:

DataTemplate yourDataTemplate = contentPresenter.ContentTemplate;

Then get the MediaElement from the DataTemplate:

TextBlock yourTextBox = yourDataTemplate.FindName("tblAlertId", contentPresenter) 
as TextBlock;
if (yourTextBox != null)
{
    alertId = Convert.ToInt32(item.Text);
executeAlertClickCommand(ConsoleSettingsModel.GetInstance().SettingsCommandsData.AlertCommand, alertId);
}

Please see the FrameworkTemplate.FindName Method page on MSDN for more information. http://msdn.microsoft.com/en-us/library/system.windows.frameworktemplate.findname.aspx

ViVi
  • 4,339
  • 8
  • 29
  • 52
  • Thanks Vishakh but I am not using the Data Template in a listbox. So I am using a DevExpress INotificationView interface where I am passing this Notification View to that interface that is present in a different class so that alerts are shown. When a alert is clicked then I want to do something. Thats why I have Border_Click. So can you help me how to find the content presenter.. I just need the textblock text in the cs file. – nikhil May 19 '16 at 03:48
  • I think the content presenter can be the Notification View here. Since you're using the data template to display the notification view. Try with that. – ViVi May 19 '16 at 04:09
0

try to find text block using LogiclTreeHelper class like,

private TextBlock GetTopParent()
    {
        DependencyObject dpParent = this.Parent;
        do
        {
            dpParent = LogicalTreeHelper.GetParent(dpParent);
        } while (dpParent.GetType().BaseType != typeof(UserControl));
        return dpParent as TextBlock;
    }

replace the line while (dpParent.GetType().BaseType != typeof(TextBlock));

  • Sure I will give it a try. Thanks. – nikhil May 19 '16 at 15:16
  • I get an exception like Value cannot be null. Parameter name: current at this line dpParent = LogicalTreeHelper.GetParent(dpParent); – nikhil May 19 '16 at 18:32
  • Hi,Nikhil sorry fro the late response you have to pass your current parent element in that argument from which you want to find your Textblock for example Usercontrol or MainWindow or it can be Grid. – Vijay Chauhan Jun 17 '16 at 08:41
0

For me, since I had added the controls at run time, I had to register them before using the findName method.

StackPanel sp = new StackPanel
{
   Name = "mySP",
   Orientation = Orientation.Horizontal,
};

//need to register the control so i can find it by name
RegisterName(sp.Name, sp);

//now I can find control by name 
StackPanel sp = (StackPanel)mainStackPanel.FindName("mySP");
Upulie Han
  • 431
  • 1
  • 7
  • 15