简体   繁体   中英

WPF access to control in template. Issue with CalendarDayButton

I'm trying to access at a Control in a Template . For this, I redefined control CalendarDayButton :

<Window.Resources>
    <Style x:Key="myStyleDayButtonCalendar" TargetType="{x:Type CalendarDayButton}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type CalendarDayButton}">
                    <Grid  Name="gridCalendar">
                        <ContentControl Margin="5,1,5,1" Content="{TemplateBinding Content}"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>

<Grid x:Name="LayoutRoot" Background="White">
    <Calendar CalendarDayButtonStyle="{StaticResource myStyleDayButtonCalendar}" Name="myCalendar"  SelectedDatesChanged="Calendar_SelectedDatesChanged_1" />
</Grid>

It's OK for that. But when I want to access at my control GRID. Impossible:

private void Calendar_SelectedDatesChanged_1(object sender, SelectionChangedEventArgs e)
{
    Grid gridInTemplate = (Grid)myCalendar.Template.FindName("gridCalendar", myCalendar) as Grid;
}

My grid is null . So, I tried with an other Control . With a Button :

<Window.Resources>
   <Style x:Key="myStyleButton" TargetType="{x:Type Button}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Grid  Name="myButton">
                        <Ellipse Fill="DarkBlue"></Ellipse>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>

<Grid x:Name="LayoutRoot" Background="White">
    <Calendar CalendarDayButtonStyle="{StaticResource myStyleDayButtonCalendar}" Name="myCalendar"  SelectedDatesChanged="Calendar_SelectedDatesChanged_1" />
    <Button Style="{StaticResource myStyleButton}" Name="myButton2" Margin="92,99,518,338" Click="myButton2_Click_1"></Button>
</Grid>

Code behind:

private void myButton2_Click_1(object sender, RoutedEventArgs e)
{
    Grid gridInTemplate = (Grid)myButton2.Template.FindName("myButton", myButton2);
}

And here gridInTemplate is NOT NULL . Why in the case dayCalendarButton gridInTemplate is NULL ? I would like to avoid to use a VisualTreeHelper .

In your case, you're trying to find a CalendarDayButton in Calendar. But these are two different controls. For example, we have a style for the calendar:

    <Style TargetType="{x:Type Calendar}">            
        <Setter Property="SnapsToDevicePixels" Value="True" />
        <Setter Property="BorderBrush" Value="Gray" />
        <Setter Property="BorderThickness" Value="1"/>

        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Calendar}">
                    <StackPanel x:Name="PART_Root" HorizontalAlignment="Center">
                        <CalendarItem x:Name="PART_CalendarItem" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" />
                    </StackPanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

In the code we can access to StackPanel like that:

    private void Calendar_SelectedDatesChanged(object sender, SelectionChangedEventArgs e)
    {
        StackPanel StackPanelInTemplate = (StackPanel)MyCalendar.Template.FindName("PART_Root", MyCalendar) as StackPanel;          
        MessageBox.Show(StackPanelInTemplate.Name);     
    }

But it is in the calendar style not exists CalendarDayButton. This a separate control. At the CalendarDayButton we can only get style:

Style MyCalendarDayButton = (Style)MyCalendar.CalendarDayButtonStyle;       

But not a template. The construction of the form:

CalendarDayButton MyCalendarDayButton = FindChild<CalendarDayButton>(MyCalendar, "gridCalendar");   

It will not work. Does not work for the reason that it is not in the same visual tree as the calendar.

Conclusion : maybe just access to CalendarDayButton will not work because it is not see in the visual tree of calendar (have designed so developers). Although I may be mistaken. I have a similar problem encountered when working with DatePicker. There can not be simply so to get access to some parts of DatePicker, for example: get access to Watermark - http://matthamilton.net/datepicker-watermark .

The decision depends on why you need it this button. Try to move your functionality in triggers like Control, Style or create your own control, inherited from the CalendarDayButton class (that tiresome). Our use converters, example:

<Grid x:Name="CalendarDayButtonGrid">                         
    <Grid.ToolTip>
          <MultiBinding Converter="{StaticResource HighlightDate}">
              <MultiBinding.Bindings>
                  <Binding />
                    <Binding RelativeSource="{RelativeSource FindAncestor, 
                               AncestorType={x:Type Calendar}}" />
              </MultiBinding.Bindings>
          </MultiBinding>
    </Grid.ToolTip>
    <!-- End addition -->
</Grid>

PS Here you are told how to use WPF ToolKit access to CalendarDayButton: http://codesticks.wordpress.com/tag/wpf-toolkit/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM