When I click a button from my form and enter a string into the Textbox that appears, I need it to create a new ObservableCollection list with that string name.
A label with the string name will then appear on the form. We then have created a ContextMenu for that label. From here you can add another string inside that list that you clicked on.
This is the save button for the string:
private void btnSave_Click(object sender, RoutedEventArgs e)
{
string titleName = txtTitle.Text;
_viewmodel.RenameTitle(titleName);
_Addtitle.Execute(null);
this.Close();
}
Then we go into the ViewModel class(titleName is the first string entered).
public ICommand AddTitleCommand { get; set; }
public ViewModel()
{
this.AddTitleCommand = new RelayCommand(new Action<object>((o) => OnAddTitle()));
}
private void OnAddTitle()
{
NewTitle += titleName;
}
The OnAddTitle() method and the two below are where the problem arises. At the moment, the titleName string is split up, and each character is displayed as a new collection (we are assuming) on the form, instead of a title being one collection. - There should be multiple titles with multiple collections, each title having its own collection. The title should be as one word instead of being split up into individual characters.
public string NewTitle
{
get { return newTitle; }
set { newTitle = value; OnPropertyChanged(() => NewTitle); }
}
public void AddCollection()
{
ObservableCollection<string> collection = new ObservableCollection<string>();
collection.Add(NewTitle);
Collections.Add(collection);
}
XAML code on the form binding an ItemsSource to the NewTitle property:
<StackPanel Name="Content" Margin="0,99,0,0">
<TextBox x:Name="txtname" Height="23" TextWrapping="Wrap" Margin="200,0,500,0"/>
<ListView x:Name="TitleList" ItemsSource="{Binding NewTitle}" ItemTemplate="{DynamicResource Template}" BorderBrush="{x:Null}">
</ListView>
</StackPanel>
EDIT:
This is what it looks like, it should appear as one string in a collection.
I highly recommend you continue researching MVVM because you'll want to change how you are using WPF. But I think your problem here is around the fact you are using an
ObservableCollection<ObservableCollection<string>>
when what you really need is something like this:
public class YourTitleClass : INotifyPropertyChanged
{
private string _title;
public string Title
{
get { return _title; }
set
{
if (_title.Equals(value))
return;
_title = value;
RaisePropertyChanged(() => Title);
}
}
private ICollection<string> _subtitles;
public ICollection<string> Subtitles
{
get
{
if (_subtitles == null)
_subtitles = new ObservableCollection<string>();
return _subtitles;
}
set
{
if (value == _subtitles)
return;
_subtitles = value;
RaisePropertyChanged(() => Subtitles);
}
}
public YourTitleClass(string title)
{
_title = title;
}
}
Then your AddCollection method needs to add an instance of this class to the ViewModels collection
public void AddCollection()
{
YourTitleClass newTitleClass = new YourTitleClass(NewTitle);
Collections.Add(newTitleClass);
}
Make sure you change the type of Collections in your ViewModel to
ObservableCollection<YourTitleClass>
Now when you add a "subtitle" (or whatever this subcollection represents), you'll add it to YourTitleClass.Subtitles. And if you are using the parent level of the object it's YourTitleClass.Title.
Related
I want to create a simple Control to enter Text.
For this Control i want to create a Property.
This Property should be bind to the ViewModel.
I Created a Model for an Folder:
public class FolderModel : ModelBase
{
private string fullPath;
public string FullPath
{
get { return fullPath; }
set
{
if (fullPath == value)
return;
fullPath = value;
RaisePropertyChanged(nameof(FullPath));
}
}
}
In my View xaml i bound the Data to my ViewModel:
<UserControl.DataContext>
<Browser:FolderBrowserViewModel/>
</UserControl.DataContext>
<Grid>
<TextBox x:Name="TextBox_Folder" IsReadOnly="True" Text="{Binding Folder.FullPath}"/>
</Grid>
To Create the Property created this code in the View:
public string FullPath
{
get { return (string)GetValue(FolderFullPathProperty); }
set { SetValue(FolderFullPathProperty, value); }
}
public static readonly DependencyProperty FolderFullPathProperty = DependencyProperty.Register("FullPath", typeof(string), typeof(FolderBrowser), new PropertyMetadata("", new PropertyChangedCallback(OnSetTextChanged)));
private static void OnSetTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
FolderBrowser UserControl1Control = d as FolderBrowser;
UserControl1Control.OnSetTextChanged(e);
}
private void OnSetTextChanged(DependencyPropertyChangedEventArgs e)
{
TextBox_Folder.Text = e.NewValue.ToString();
}
My ViewModel looks like this:
private ICommand _browseFolderCommand;
public ICommand BrowseFolderCommand
{
get
{
return _browseFolderCommand is null ? (_browseFolderCommand = new RelayCommand(() => BrowseFolder(), true)) : _browseFolderCommand;
}
}
private FolderModel folder = new FolderModel();
public FolderModel Folder
{
get { return folder; }
set
{
if (folder == value)
return;
folder = value;
}
}
private void BrowseFolder()
{
System.Windows.Forms.FolderBrowserDialog fbd = new System.Windows.Forms.FolderBrowserDialog();
if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
SetField(ref folder, Folder, "FullPath");
}
}
and my ViewModelBase looks like this:
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}
protected void Dispatch(Action f) => Application.Current.Dispatcher.Invoke(f);
protected TResult Dispatch<TResult>(Func<TResult> f) => Application.Current.Dispatcher.Invoke(f);
}
if i use the Control i want to set the Property "FullPath"
when i set this Property the Value should be set to the ViewModels Folder.FullPath.
If this is set, the Binding of the TextBox and Folder.FullPath should show the correct path.
if its possible i want all Code in the ViewModel =)
Edit:
I tried to illustrate it a bit more pictorially:
On the left side you can see the control as it is placed on a window. There you can set MyProp to any value and the TextBox will receive it.
On the right side I have tried to show it in more detail.
The view has the label, a TextBox and a button.
The view also has the property "MyProp".
The textbox of the view is bound to the ViewModel, namely to the field "MyCoolFieldValue".
This means that if I do anything in the ViewModel with the field MyCoolFieldValue, I know that it will always have the value that is in the textbox.
If I now press the button, a command is called. This command changes the WErt of MyCoolFieldValue. When this happens, the value should be written directly back into the property and the textbox of the view.
However, I can't get this to work and have tried it with the code above.
My goal is to output a list in a datagrid, but this doesn't work and the datagrid is empty.
I tried to display the list in an other way and it did (but I can't remember what it was) and it worked, except for it not being in a datagrid but just data. I have changed up some things, but back then it reached the end and got displayed.
ViewModel in Mainwindow:
public class ViewModel
{
public List<ssearch> Items { get; set; }
private static ViewModel _instance = new ViewModel();
public static ViewModel Instance { get { return _instance; } }
}
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
//For simplicity, let's say this window opens right away
var Mdata = new MDataWindow { DataContext = DataContext };
Mdata.Show();
}
Other Window for data display:
string searchParam = "status = 1";
public MDataWindow()
{
InitializeComponent();
}
private void AButton_Click(object sender, RoutedEventArgs e)
{
MainWindow.ViewModel.Instance.Items = Search(searchParam);
}
public List<ssearch> Search(string where)
{
{
//Lots of stuff going on here
}
return returnList;
}
And in WPF:
<Window x:Class="WPFClient.MDataWindow"
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:WPFClient"
mc:Ignorable="d"
Title="MDataWindow" Height="Auto" Width="Auto">
<StackPanel>
<Button x:Name="AButton" Click="AButton_Click" Content="Load" />
<DataGrid ItemsSource="{Binding Items}" />
</StackPanel>
</Window>
I have no clue where the error is and tried to strip the code down as much as possible without killing error sources. The Datagrid just stays empty when I press the "Load" button.
EDIT:
I tried to convert the list into an observableColletion before passing it to the ViewModel, but this didn't work. I am working with a library, which I am not sure how to use observableCollection with, so I converted it instead of using it right away:
VM:
public ObservableCollection<Product> Items { get; set; }
Data Window:
List<Product> pp = Search_Products(searchParam);
var oc = new ObservableCollection<Product>(pp);
MainWindow.ViewModel.Instance.Items = oc;
First, change your List<Product> to an ObservableCollection<Product> as this will help to display the Items of the list on Add/Remove immediately.
This is because ObservableCollection implements the INotifyCollectionChanged interface to notify your target(DataGrid) to which it is bound, to update its UI.
Second, your binding can never work as expected due to changed reference of your collection.
private void AButton_Click(object sender, RoutedEventArgs e)
{
// You are changing your Items' reference completely here, the XAML binding
// in your View is still bound to the old reference, that is why you're seeing nothing.
//MainWindow.ViewModel.Instance.Items = Search(searchParam);
var searchResults = Search(searchParam);
foreach(var searchResult in searchResults)
{
MainWindow.ViewModel.Instance.Items.Add(searchResult);
}
}
Make sure you have changed the List to ObservableCollection upon running the Add loop, else you will get an exception saying the item collection state is inconsistent.
The ViewModel class should implement the INotifyPropertyChanged interface and raise its PropertyChanged event whenever Items is set to a new collection:
public class ViewModel : INotifyPropertyChanged
{
private List<ssearch> _items;
public List<ssearch> Items
{
get { return _items; }
set { _items = value; OnPropertyChanged(); }
}
private static ViewModel _instance = new ViewModel();
public static ViewModel Instance { get { return _instance; } }
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
This is required to notify the view regardless of the type of Items.
If you change the type of Items to ObservableCollection<T>, you should initialize the collection in the view model once:
public class ViewModel
{
public ObservableCollection<ssearch> Items { get; } = new ObservableCollection<ssearch>();
private static ViewModel _instance = new ViewModel();
public static ViewModel Instance { get { return _instance; } }
}
...and then add items to this collection instead of setting the property to a new one:
private void AButton_Click(object sender, RoutedEventArgs e)
{
MainWindow.ViewModel.Instance.Items.Clear();
var search = Search(searchParam);
if (search != null)
foreach (var x in search)
MainWindow.ViewModel.Instance.Items.Add(x);
}
I've a problem with DataGrid in Prism MVVM.
When I edited entity in other window, then I create new window with DataGrid is not updated. Only run application again help. It's my code:
<DataGrid Name="ClientsTable" IsReadOnly="True" ItemsSource="{Binding Path=ListOfClients, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" AutoGeneratingColumn="DataGrid_AutoGeneratingColumn" Margin="22,10,22,55" Width="800"/>
Part of ViewModel for this window:
public ListOfClientsViewModel(IClientService clientService, IEventAggregator eventAggregator)
{
this.clientService = clientService;
this.eventAggregator = eventAggregator;
ListOfClients.AddRange(clientService.GetAllClientsForList());
}
private ObservableCollection<ClientForList> listOfClients = new ObservableCollection<ClientForList>();
public ObservableCollection<ClientForList> ListOfClients
{
get { return listOfClients; }
set { SetProperty(ref listOfClients, value); }
}
And part of model from collection. It's in other project.
public class ClientForList : INotifyPropertyChanged
{
private string id;
private string name;
private string firstname;
private string lastname;
private string city;
private DateTime createdDate;
[DisplayName("Numer klienta")]
public string Id
{
get { return id; }
set
{
if (value != id)
{
id = value;
OnPropertyChanged();
}
}
}
[DisplayName("Nazwa")]
public string Name
{
get { return name; }
set
{
if (value != name)
{
name = value;
OnPropertyChanged();
}
}
}
[DisplayName("ImiÄ™")]
public string Firstname
{
get { return firstname; }
set
{
if (value != firstname)
{
firstname = value;
OnPropertyChanged();
}
}
}
[.....]
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
And, when I edit entity in other window, then I open window with DataGrid by:
void ExecuteListOfClients()
{
ListOfClients listOfClientsWindow = new ListOfClients();
listOfClientsWindow.DataContext = new ListOfClientsViewModel(IClientService, EventAggregator);
listOfClientsWindow.ShowDialog();
}
And data in DataGrid is old. When I restart application data is actual. Help!
Instead of
set { SetProperty(ref listOfClients, value); }
do
set { SetProperty(listOfClients, value); }
and instead of
ListOfClients.AddRange(clientService.GetAllClientsForList());
do
ListOfClients = clientService.GetAllClientsForList().ToObservableCollection();
You may need to implement the extension ToObservableCollection().
Another solution is to change the property ListOfClients as a normal IList and then implment INotifyPropertyChanged inside your view model
Ok, I solved part of the problem.
I have cut the window creation without the manual creation of the ViewModel on:
void ExecuteListOfClients()
{
ListOfClients listOfClientsWindow = new ListOfClients();
listOfClientsWindow.ShowDialog();
}
And in xaml ListOfClients.xaml I changed to:
prism:ViewModelLocator.AutoWireViewModel="True"
And now, after reopening the window, it shows refreshed data;)
But there is still a problem. I've done the LoadData method, which is done in the constructor and assigns data to the ObservableCollection. It works. I have set a button for it and after editing the client I click to load new data and unfortunately nothing happens. In the future I want this method to be called from the EventAggregator after editing the client, but for now I have made a button to test and unfortunately it does not work.
It works. The problem was not in the WPF itself, nor was the view strangely enough. The problem lay in EntityFramework. I had to modify the command choosing data from the database to the collection:
var clients = db.Clients.AsNoTracking().ToList();
Is it possible to have one ViewModel for multiple dynamic Tabs? Meaning that, whenever I create a new tab, it should use the same instance of ViewModel so I can retrieve information and also prevent each Tab from sharing data/showing the same data.
The setting I'm thinking of using it in would be for a payroll application where each employee's payslip can be updated from each tab. So the information should be different in each Tab.
Is this possible?
Update: Added code
MainViewModel where Tabs Collection is handled:
public ObservableCollection<WorkspaceViewModel> Workspaces { get; set; }
public MainViewModel()
{
Workspaces = new ObservableCollection<WorkspaceViewModel>();
Workspaces.CollectionChanged += Workspaces_CollectionChanged;
}
void Workspaces_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null && e.NewItems.Count != 0)
foreach (WorkspaceViewModel workspace in e.NewItems)
workspace.RequestClose += this.OnWorkspaceRequestClose;
if (e.OldItems != null && e.OldItems.Count != 0)
foreach (WorkspaceViewModel workspace in e.OldItems)
workspace.RequestClose -= this.OnWorkspaceRequestClose;
}
private void OnWorkspaceRequestClose(object sender, EventArgs e)
{
CloseWorkspace();
}
private DelegateCommand _exitCommand;
public ICommand ExitCommand
{
get { return _exitCommand ?? (_exitCommand = new DelegateCommand(() => Application.Current.Shutdown())); }
}
private DelegateCommand _newWorkspaceCommand;
public ICommand NewWorkspaceCommand
{
get { return _newWorkspaceCommand ?? (_newWorkspaceCommand = new DelegateCommand(NewWorkspace)); }
}
private void NewWorkspace()
{
var workspace = new WorkspaceViewModel();
Workspaces.Add(workspace);
SelectedIndex = Workspaces.IndexOf(workspace);
}
private DelegateCommand _closeWorkspaceCommand;
public ICommand CloseWorkspaceCommand
{
get { return _closeWorkspaceCommand ?? (_closeWorkspaceCommand = new DelegateCommand(CloseWorkspace, () => Workspaces.Count > 0)); }
}
private void CloseWorkspace()
{
Workspaces.RemoveAt(SelectedIndex);
SelectedIndex = 0;
}
private int _selectedIndex = 0;
public int SelectedIndex
{
get { return _selectedIndex; }
set
{
_selectedIndex = value;
OnPropertyChanged("SelectedIndex");
}
}
WorkspaceViewModel:
public PayslipModel Payslip { get; set; }
public WorkspaceViewModel()
{
Payslip = new PayslipModel();
SaveToDatabase = new DelegateCommand(Save, () => CanSave);
SelectAll = new DelegateCommand(Select, () => CanSelect);
UnSelectAll = new DelegateCommand(UnSelect, () => CanUnSelect);
}
public ICommand SaveToDatabase
{
get; set;
}
private bool CanSave
{
get { return true; }
}
private async void Save()
{
try
{
MessageBox.Show(Payslip.Amount.ToString());
}
catch (DbEntityValidationException ex)
{
foreach (var en in ex.EntityValidationErrors)
{
var exceptionDialog = new MessageDialog
{
Message = { Text = string.Format("{0}, {1}", en.Entry.Entity.GetType().Name, en.Entry.State) }
};
await DialogHost.Show(exceptionDialog, "RootDialog");
foreach (var ve in en.ValidationErrors)
{
exceptionDialog = new MessageDialog
{
Message = { Text = string.Format("{0}, {1}", ve.PropertyName, ve.ErrorMessage) }
};
await DialogHost.Show(exceptionDialog, "RootDialog");
}
}
}
catch (Exception ex)
{
var exceptionDialog = new MessageDialog
{
Message = { Text = string.Format("{0}", ex) }
};
await DialogHost.Show(exceptionDialog, "RootDialog");
}
}
public event EventHandler RequestClose;
private void OnRequestClose()
{
if (RequestClose != null)
RequestClose(this, EventArgs.Empty);
}
private string _header;
public string Header
{
get { return _header; }
set
{
_header = value;
OnPropertyChanged("Header");
}
}
Payroll UserControl where WorkspaceViewModel is DataContext:
public Payroll()
{
InitializeComponent();
DataContext = new WorkspaceViewModel();
}
Payroll.xaml Tabcontrol:
<dragablz:TabablzControl ItemsSource="{Binding Workspaces}" SelectedIndex="{Binding SelectedIndex}" BorderBrush="{x:Null}">
<dragablz:TabablzControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Header}"/>
</DataTemplate>
</dragablz:TabablzControl.ItemTemplate>
<dragablz:TabablzControl.ContentTemplate>
<DataTemplate>
<ContentControl Margin="16">
<local:TabLayout DataContext="{Binding Path=Payslip, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" x:Name="tabLayout"/>
</ContentControl>
</DataTemplate>
</dragablz:TabablzControl.ContentTemplate>
</dragablz:TabablzControl>
This works as expected, each tab displays different info and bindings work okay. However, I'm unable to retrieve the info in the MessageBox.
I'm not sure if I totally understand your question but if you need a Window with a tabcontrol, in which each tab refers to an employee, then you will have to bind the ItemsSource of the tabcontrol to a list of the ViewModel.
It is not possible to bind all tabpages to the same instance because then the tabpages will all do the same, and show the same information.
I couldn't get it to work the way I had it, so I placed the save button inside the view that has DataContext set to where employee's info are loaded and got it to work from there, since it directly accesses the properties.
ViewModels should have a 1:1 relationship with the model. In your TabControl's DataContext, let's say you have properties like:
public ObservableCollection<EmployeeViewModel> Employees {get;set;}
public EmployeeViewModel CurrentEmployee
{
get { return _currentEmployee;}
set
{
_currentEmployee = value;
OnPropertyChanged("CurrentEmployee");
}
}
where Employees is bound to ItemsSource of the TabControl, and CurrentEmployee to CurrentItem. To create a new tab:
var employee = new Employee();
var vm = new EmployeeViewModel(employee);
Employees.Add(vm);
CurrentEmployee = vm;
If you want a save button outside of the TabControl, just set its DataContext to CurrentEmployee.
I hope this helps!
Edit:
Two things I think are causing problems:
Payroll.xaml should be bound to MainViewModel since that's where the Workspaces collection is.
Do not instantiate ViewModels in your view's code behind. Use a DataTemplate instead (see this question).
Take a look at Josh Smith's MVVM demo app (source code)
I want to pass a value from MainWindow into my UserControl! I passed a value to my UserControl and the UserControl showed me the value in a MessageBox, but it is not showing the value in a TextBox. Here is my code:
MainWindow(Passing Value To UserControl)
try
{
GroupsItems abc = null;
if (abc == null)
{
abc = new GroupsItems();
abc.MyParent = this;
abc.passedv(e.ToString(), this);
}
}
catch (Exception ee)
{
MessageBox.Show(ee.Message);
}
UserControl
public partial class GroupsItems : UserControl
{
public MainWindow MyParent { get; set; }
string idd = "";
public GroupsItems()
{
InitializeComponent();
data();
}
public void passedv(string id, MainWindow mp)
{
idd = id.ToString();
MessageBox.Show(idd);
data();
}
public void data()
{
if (idd!="")
{
MessageBox.Show(idd);
texbox.Text = idd;
}
}
}
EDIT(using BINDING and INotifyProperty )
.....
public GroupsItems()
{
InitializeComponent();
}
public void passedv()
{
textbox1.Text = Text;
}
}
public class Groupitm : INotifyPropertyChanged
{
private string _text = "";
public string Text
{
get { return _text; }
set
{
if (value != _text)
{
_text = value;
NotifyPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Problem here is with reference.
When you create new object in code behind, new object will be created and this is not the same object which you have in xaml code. So you should use following code:
<local:GroupsItems x:Name="myGroupsItems"/>
and in code behind you don't have to create new object. You should use object that you added in XAML:
...
myGroupsItems.MyParent = this;
myGroupsItems.passedv(e.ToString(), this);
...
Here is example solution (sampleproject).
You are calling data in the constructor when idd is still "" which results in the text box still being empty. Changing the MyParent property does not change that. Only passedv does. But at that point you do not have the parent set. Just call data in passedv, too.
Try this:
public partial class GroupsItems : UserControl
{
//properties and methods
private string idd="";
public string IDD
{
get{return idd;}
set{
idd=value;
textBox1.Text=idd;
}
}
//other properties and methods
}
Usage:
In your Main form:
abc = new GroupsItems();
abc.IDD="sometext";
MainGrid1.Children.Add(abc); //Grid or any other container for your UserControl
In your Binding example, your GroupItem class looks ok, except that you need to pass in the name of the changed property:
public string Text
{
get { return _text; }
set
{
if (value != _text)
{
_text = value;
NotifyPropertyChanged("Text");
}
}
}
Now, in GroupsItems, you shouldn't be accessing the TextBox. In WPF, we manipulate the data, not the UI... but as we use Binding objects to data bind the data to the UI controls, they automatically update (if we correctly implement the INotifyPropertyChanged interface).
So first, let's add a data property into your code behind (which should also implement the INotifyPropertyChanged interface) like you did in your GroupItem class:
private GroupItem _item = new GroupItem();
public GroupItem Item
{
get { return _item; }
set
{
if (value != _item)
{
_item = value;
NotifyPropertyChanged("Item");
}
}
}
Now let's try using a Binding on a TextBox.Text property:
<TextBox Text="{Binding Item.Text}" />
See how we bind the Text property of your GroupItem class to the TextBox.Text property... now all we need to do is to change the value of the Item.Text property and watch it update in the UI:
<Button Content="Click me" Click="Button_Click" />
...
private void Button_Click(object sender, RoutedEventArgs e)
{
Item.Text = "Can you see me now?";
}
Alternatively, you could put this code into your passedv method if you are calling that elsewhere in your project. Let me know how you get on.
UPDATE >>>
In your GroupItem class, try changing the initialization to this:
private string _text = "Any text value";
Can you now see that text in the UI when you run the application? If not, then try adding/copying the whole Text property into your code behind and changing the TextBox declaration to this:
<TextBox Text="{Binding Text}" />
If you can't see the text value now, you've really got problems... you have implemented the INotifyPropertyChanged interface in your code behind haven't you?