Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replacing UserControl by property

I have two User Control's sitting in main UserCotrol.

only one of them should be in the main.

when you change certain property in the ViewModel, I change them like this:

<UserControl>
    <ContentControl>
        <ContentControl.Style>
            <Style TargetType="{x:Type ContentControl}">
                <Setter Property="Content">
                    <Setter.Value>
                        <local:UserControl1/>
                    </Setter.Value>
                </Setter>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding IsTwo}" Value="True">
                        <Setter Property="Content">
                            <Setter.Value>
                                <local:UserControl2/>
                            </Setter.Value>
                        </Setter>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </ContentControl.Style>
    </ContentControl>
</UserControl>

When I change the property to False it goes to UserControl1 without problems, but when I change it to True, there are problems with the display and only when I'm moving between screens it fit, as a temporary solution, I created event every time that UserControl should change from 1 to 2 . When that event runs I delete the main UserControl and create it again.

But my question is why when I change to one I do not need to re-create, and when I change to two I might need?

Do not give me any ideas how to solve this (I've done it myself), I want explain why this is happening, this is what interests me.

like image 992
Hodaya Shalom Avatar asked Mar 18 '13 08:03

Hodaya Shalom


1 Answers

You WPF is fine; I cannot reproduce your problem; Start a new WPF application and dump this into it: then replace with your user control (remember you might need to bind the user control up in your template if you want it bound to something specific)

ViewModel.cs:

public class ViewModel : INotifyPropertyChanged
{
    private bool _isTwo;

    public bool IsTwo
    {
        get { return _isTwo; }
        set
        {
            _isTwo = value;
            OnPropertyChanged("IsTwo");
        }
    }

    public ICommand Switch
    {
        get { return new RelayCommand((_) => { IsTwo = !IsTwo; }, (_) => true); }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

public class RelayCommand : ICommand
{
    private readonly Action<object> _action;
    private readonly Func<object, bool> _predicate;

    public RelayCommand(Action<object> action, Func<object, bool> predicate)
    {
        _action = action;
        _predicate = predicate;
    }

    public bool CanExecute(object parameter)
    {
        return _predicate(parameter);
    }

    public void Execute(object parameter)
    {
        _action(parameter);
    }

    public event EventHandler CanExecuteChanged;
}

MainWindow

<Window.DataContext>
    <local:ViewModel/>
</Window.DataContext>

<DockPanel>
    <Button DockPanel.Dock="Top" Command="{Binding Switch}"> Switch </Button>
    <UserControl>
        <ContentControl >
            <ContentControl.Style>
                <Style TargetType="{x:Type ContentControl}">
                    <Setter Property="Content">
                        <Setter.Value>
                            <local:UserControl1 DataContext="{Binding UserControl1ViewModel}"/>
                        </Setter.Value>
                    </Setter>
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding IsTwo}" Value="True">
                            <Setter Property="Content">
                                <Setter.Value>
                                    <local:UserControl2/>
                                </Setter.Value>
                            </Setter>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </ContentControl.Style>
        </ContentControl>
        </UserControl>
</DockPanel>

Create two new (empty) UserControls and set two different colours:

OffOn

Replace one of these with your troubled user controller. If you have layout issues, in all likelihood your user controls are trying to resize themselves, or you need to put them in a better container. I'm sticking the above into a DockPanel. Which is generally quite good at expanding controls into the the available space.

[Edit]

So if you want to know what is created when, slap this some messageboxes into your user control's ctor

public UserControl1()
{
    InitializeComponent();

    MessageBox.Show("Created UserControl1");
}

public UserControl2()
{
    InitializeComponent();

    MessageBox.Show("Created UserControl2");
}

For me, both of them are created on application start. i.e. UserControl2 isn't visible yet, but is created. One would presume it isn't bound until the Data Trigger switches; but if you are doing some code-behind in your user control, that may screw up WPF.

like image 181
Meirion Hughes Avatar answered Oct 29 '22 18:10

Meirion Hughes