Home > Back-end >  WPF Databinding to second view
WPF Databinding to second view

Time:11-23

I have spend a little over a Day on this problem and i am absolutely Clueless. If i click the button to show the Second View it Opens, but without Content. I even get by a breakpoint in the View Model. For this i have reduced everything to a Simple Textbox and Textblock that shut display the same Data, but they do not. They show nothing even after Typing into the Box the Block does not update. But what ever i try the Databinding does not Work. Does anyone has an Idea?

Thanks in Advance

My second View

<Window x:Class="AoE4_BO_Overlay.Views.EditorView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:AoE4_BO_Overlay.Views" xmlns:viewmodels="clr-namespace:AoE4_BO_Overlay.ViewModels" d:DataContext="{d:DesignInstance Type=viewmodels:EditorViewModel}"
    mc:Ignorable="d"
    Title="EditorView" Height="450" Width="800">
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="auto" />
        <ColumnDefinition Width="20" />
        <ColumnDefinition Width="20" />
    </Grid.ColumnDefinitions>

    <Grid.RowDefinitions>
        <RowDefinition Height="20" />
        <RowDefinition Height="auto" />
        <RowDefinition Height="auto" />
        <RowDefinition Height="20" />
    </Grid.RowDefinitions>
    <TextBlock Text="{Binding Path=FirstName}" Grid.Column="0" Grid.Row="2"/>
    <TextBox Text="{Binding Path=FirstName , Mode=OneWay}" Grid.Column="0" Grid.Row="1"/>
</Grid>

My ViewModel

    internal class EditorViewModel : Conductor<object>
{
    private string _firstName = "Tom";
    public EditorViewModel()
    {
    }

    public string FirstName
    {
        get
        {

            return _firstName;
        }
        set
        {
            _firstName = value;
            NotifyOfPropertyChange(() => FirstName);
        }
    }
}

How i call both of them

        public void CreateBO_Click(object sender, RoutedEventArgs e)
    {
        EditorView createBO = new EditorView();
        ActivateItemAsync(new EditorViewModel());
        createBO.Show();
    }

added Information

    public partial class EditorView : Window
{
    public EditorView()
    {
        DataContext = new EditorViewModel();
        InitializeComponent();
    }
}

CodePudding user response:

You have two separate issues:

1. Typing into the textbox doesn't change the bound property:

This is expected, since you use OneWay binding explicitly. OneWay binding means the property updates the user interface, but not the other way around. So changing FirstName should update the TextBox, but changing the TextBox doesn't update FirstName.

Interestingly enough, if you just omit the Mode = OneWay part, it should work - since TextBoxes should use TwoWay binding by default. I recommend you define your TextBox binding explicitly as Mode = TwoWay

2. Your view initializes with an empty TextBlock / TextBox

This one is harder to pin down, since you don't show us where you set your DataContext. This usually happens to me when I set the DataContext AFTER InitializeComponent(), instead of before. You either set the DataContext before the binding is initialized (as part of InizializeComponent()), or you have to raise a NotifyPropertyChanged on your property to update the UI afterwards.

If this is not the cause, you might want to enable WPF binding errors in your output console - that usually gives you a good idea of where your bindings fail. Visual Studio has an option for that. It should be located here:

Tools -> Options -> Debugging -> Output Window -> WPF Trace Settings -> Data Binding -> All

CodePudding user response:

I believe what you are attempting here is to show your second View (EditorView) within the first one (and not as a pop-up - if you intend to have it as popup, use WindowManager instead of ActivateItemAsync).

One thing you need to change for making this possible is to ensure your second View is a UserControl and not a Window.

// EditorView.xaml.cs
public partial class EditorView : UserControl

// EditView.xaml
<UserControl x:Class="AoE4_BO_Overlay.Views.EditorView"

Also since your using the ActivateItemAsync, you would need to ensure that your FirstView contains a ContendControl with Name "ActiveItem".

// FirstView.xaml
<ContentControl x:Name="ActiveItem"/>

The call to ActivateItemAsync would use this control to load the View of your second ViewModel (EditorViewModel). With this in place, you could now use the ActivateItemAsync method to load the View.

public async Task CreateBO_Click(object sender, RoutedEventArgs e)
{
   await ActivateItemAsync(new EditorViewModel());
}

Please note that method ActivateItemAsync supports asynchronous calls and it would be wise to call the method asynchronously.

Another point to note is that you do not need to specify the DataContext explicitly as seen in the OP if you are using Caliburn Micro and the View/ViewModels are stored in the recommended folder/namespaces structures. Caliburn Micro uses naming conventions to associate the appropriate view-viewmodel pairs. More information on the same could be found in the official documentation

  • Related