简体   繁体   中英

Modify Grid of a UserControl in MainPage.xaml

I found many threads about this topic but couldn't make my app working, so I ask a new question here.

I want to make a UserControl-element that has a Grid that can be filled from outside. this is the UserControl-Xaml-Part:

<Grid>
    <Grid.ColumnDefinitions>
         <ColumnDefinition Width="70"/>
         <ColumnDefinition Width="*"/>
         <ColumnDefinition Width="Auto"/>
         <ColumnDefinition Width="*"/>
         <ColumnDefinition Width="70"/>
     </Grid.ColumnDefinitions>

     <Grid Grid.Column="2" x:Name="ButtonGrid"/>
</Grid>

Outside in my MainPage.xaml I want to use it like this:

<UserControls:MyControl>
    <UserControls:MyControl.ButtonGrid>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="130"/>
                <ColumnDefinition Width="130"/>
                <ColumnDefinition Width="130"/>
                <ColumnDefinition Width="130"/>
            </Grid.ColumnDefinitions>
            // Add elements and stuff
        </Grid>
    </UserControls:MyControl.ButtonGrid>
</UserControls:AppBar>

But I don't get this far. It says that "ButtonGrid" was not recognized or couldn't access Member (my translation from german error-message). But when I type UserControls:MyControl. it suggests ButtonGrid .

The MyControl.xaml.cs looks like this:

namespace myApp
{
    public partial class MyControl: UserControl
    {
        public Grid ButtonGrid { get; set; }

        // or
        public Grid ButtonGrid
        {
            get { return (Grid)GetValue(ButtonGridProperty); }
            set { SetValue(ButtonGridProperty, value); }
        }
        public static readonly DependencyProperty ButtonGridProperty =
            DependencyProperty.Register("ButtonGrid", typeof(Grid), typeof(MyControl), new PropertyMetadata(new Grid()));

        public MyControl()
        {
            InitializeComponent();
        }
    }
}

I tried many ways of making this "ButtonGrid"-value visible and working but still it doesn't. Any Ideas?

EDIT I can get the Grid in the codebehind with a simple getter. But its just not straight-forward to create stuff somewhere and THEN put them to the place I want them to be.

Setting a Name on an element in XAML creates a private field for that object that you can then access in code-behind. It does not make it a placeholder for other content as you're trying to use it. If you want to inject external content into your XAML use a ContentPresenter or some ContentControl derivative and set the content you want to inject to its Content property. This is the pattern used in general for ContentControls so you can look at the default template for Button for example and see this pattern.

So to use this:

<local:MyControl>
  <local:MyControl.CustomContent>
    <Grid>
      <!-- elements and stuff to pass in -->
    </Grid>
  </local:MyControl.CustomContent>
</local:MyControl>

You would have a DependencyProperty in MyControl (CustomContent) like you tried already (but it should be type object unless you have a specific reason for some other type). Then your control's XAML would look more like:

<Grid>
  <Grid.ColumnDefinitions>
    ...
  </Grid.ColumnDefinitions>

  <ContentPresenter Grid.Column="2" Content="{Binding CustomContent, RelativeSource={RelativeSource FindAncestor, AncestorType=local:MyControl}}"/>
</Grid>

Thanks to John Bowen for the right idea. Now the best solution I've got so far is: MainPage.xaml

<local:MyControlx:Name="Control" Grid.Row="1" Grid.RowSpan="2"
                                Height="98" VerticalAlignment="Bottom">
    <local:MyControl.Content>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="130"/>
                <ColumnDefinition Width="130"/>
                <ColumnDefinition Width="130"/>
                <ColumnDefinition Width="130"/>
            </Grid.ColumnDefinitions>

        <!-- Stuff inside that works! -->

        </Grid>
    </local:MyControl.Content>
</local:MyControl>

And MyControl.xaml (which is a ContentControl now!):

<Grid x:Name="MyCtrl" Background="{StaticResource PhoneAccentBrush}"
      Height="98" VerticalAlignment="Bottom"
      Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ActualWidth}">
    <Grid.RenderTransform>
        <TranslateTransform x:Name="moveTransform" />
    </Grid.RenderTransform>

    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="70"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="*"/>
       <ColumnDefinition Width="70"/>
    </Grid.ColumnDefinitions>

    <ContentPresenter Grid.Column="2"
                      Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DataContext}"/>

    <!-- Buttons and stuff that should be always there in Grid.Column=0 and Grid.Column=4 -->

    </Button>
</Grid>

The buttons and stuff from MainPage.xaml are visible, clickable and nothing crashes. But I don't see the buttons or PhoneAccentBrush-background from the inside of MyControl.xaml =/ So this must be the right way I just miss something..

Edit: If I make MyControl to a UserControl the .Content overwrites everything that was inside. If I make it a ContentControl it seems to see the inner Grid because it places everything almost in the right place. But still I can't see any other elements that are declared inside the MyControl. If I don't set the .Content I see all internal stuff, all methods working but of course nothing that I wanted to place inside is there.

Edit2: I've managed it somehow but stumbled into new errors. But I guess its better to link the other thread ;) Keep a reference to objects passed to a UserControl

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