Command binding in nested data template + wpf + mvvm - c#

I need to pass values from view to view model still preserving mvvm. Let me explain the issue.
<UserControl x:Class="SelectorView" ...>
<ListView Name="gridListView" ItemsSource="{Binding... }">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Focusable" Value="false"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Border>
<StackPanel Orientation="Vertical">
<Label x:Name="vLabel" Content="{Binding VCValue}"/>
<ListView Name="checkBoxListView" ItemsSource="{Binding CList}">
<ListView.ItemTemplate>
<DataTemplate>
<CheckBox Command="{Binding DataContext.OnCheckedCommand,RelativeSource={RelativeSource Mode=Self}}" Margin="5" Click="CheckBox_Click" IsChecked="{Binding SelectedValue, Mode=TwoWay}" Content="{Binding Current, Mode=OneWay }"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</UserControl>
In above code, When user checks/unchecks the checkbox, i need to send value(content) of checkbox and also value of vLabel from view to view model. Both are within nested Data template. Earlier I used visualtreehelper to retrieve the same but I need to do this more in mvvm format. Hence, want to know if its doable using Command binding and how ? In check box, i binded to OnCheckedCommand but that doesn't seem to invoke OnCheckedExecuted() on check/uncheck.
So, how do i get the content of checkbox and vLabel on check/uncheck?
public class MainViewModel
{
public DelegateCommand<object> OnCheckedCommand { get; private set; }
public MainViewModel()
{
OnCheckedCommand = new DelegateCommand<object>(OnCheckedExecuted, CanCheck);
}
private void OnCheckedExecuted(object parameter)
{
}
private bool CanCheck(object parameter)
{
return true;
}
}
Any help is appreciated!

Related

How to show the checked items in my CheckBox

EDITED:
I've created three ListBoxes:
1st ListBox: listBox, which shows a list of U.S. States
2nd ListBox: listBox_Mirror, which contains a CheckBox to show the selected items of "listBox"
3rd ListBox: (No Name), which is supposed to show the checked items of "listBox_Mirror"
1st ListBox -> 2nd ListBox works fine. However, 2nd ListBox -> 3rd ListBox doesn't work, as you can see in the picture below:
Procedure:
Select all four items in the 1st ListBox.
Check the first two items (California and Illioni) in the 2nd ListBox's CheckBox.
See if California and Illioni are shown in the 3rd ListBox.
(In my case, nothing is shown.)
Here are my codes:
StateList.cs
using System.Collections.ObjectModel;
namespace CheckedListBox
{
public class StateList
{
public ObservableCollection<string> Data { get; }
public StateList()
{
Data = new ObservableCollection<string>();
Data.Add("California");
Data.Add("Illinoi");
Data.Add("Michigan");
Data.Add("New York");
}
}
}
MainWindow.xaml
<Window x:Class="CheckedListBox.MainWindow"
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:CheckedListBox"
mc:Ignorable="d"
Title="MainWindow" Height="500" Width="400">
<Grid>
<ListBox ItemsSource="{Binding Path=Data}" x:Name="listBox" Margin="100,50,100,300" SelectionMode="Multiple"/>
<ListBox ItemsSource="{Binding SelectedItems, ElementName=listBox}" x:Name="listBox_Mirror" Margin="100,200,100,150">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<CheckBox Content="{TemplateBinding Content}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
<ListBox ItemsSource="{Binding SelectedItems, ElementName=listBox_Mirror}" Margin="100,350,100,25"/>
</Grid>
MainWindow.xaml.cs
using System.Windows;
namespace CheckedListBox
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new StateList();
}
}
}
... I've changed the Binding property of the 3rd ListBox based on the IntelliSense's suggestion, but it doesn't work, too.
Please tell me how to fix this. Thank you.
Two things, there is no binding to the IsChecked and hence nothing ever is set. Also your data is just reference of strings; you should change it to a class with at least two properties, one a Boolean and the other the string you have now. Then bind appropriately.
Here is how to do it. I have a model which is defined in code behind but you can get the idea on its structure.
<Page ...
xmlns:model="clr-namespace:WPFStack.Model"/>
...
<Page.Resources>
<model:Orders x:Key="Orders">
<model:Order CustomerName="Alpha"
OrderId="997"
InProgress="True" />
<model:Order CustomerName="Beta"
OrderId="998"
InProgress="False" />
<model:Order CustomerName="Omega"
OrderId="999"
InProgress="True" />
<model:Order CustomerName="Zeta"
OrderId="1000"
InProgress="False" />
</model:Orders>
Now with my Listbox
<ListBox ItemsSource="{StaticResource Orders}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel HorizontalAlignment="Stretch" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding CustomerName}"
IsChecked="{Binding InProgress, Mode=TwoWay}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Running it shows this:
Model
namespace WPFStack.Model
{
/// <summary>Class Orders which is a placeholder for Xaml example data.</summary>
public class Orders : List<Order> { }
public class Order
{
public string CustomerName { get; set; }
public int OrderId { get; set; }
public bool InProgress { get; set; }
}
}
Mirror
Ok, now I will name the controls lbOriginal and lbSelected to be accessible in the code behind. The new control lbSelected will mirror as such without directly connecting to the lbOriginal control or the data:
<ListBox x:Name="lbShowSelected">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel HorizontalAlignment="Stretch" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding .}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Then I would subscribe to events such as Loaded, Checked and UnChecked on the original.
<ListBox x:Name="lbOriginal"
ItemsSource="{StaticResource Orders}"
Loaded="ProcessChange">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel HorizontalAlignment="Stretch" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding CustomerName}"
IsChecked="{Binding InProgress, Mode=TwoWay}"
Checked="ProcessChange"
Unchecked="ProcessChange"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
So then at each step ProcessChange method properly updates the mirror (selected as I call it):
private void ProcessChange(object sender, RoutedEventArgs e)
{
if (lbOriginal.ItemsSource is Orders asOrders)
{
lbShowSelected.ItemsSource = null; // Inform control of reset
lbShowSelected.ItemsSource = asOrders.Where(ord => ord.InProgress)
.Select(ord => ord.CustomerName)
.ToList();
}
}
Then it is in sync and mirroring

C# Wpf create dynamic check boxes next to one another

Problem
I have a dynamic list of reports gathered from a database, and each of them will have the option to be exported in one of two formats, both, or neither. I would like this to be represented as a list of all reports with two adjacent checkboxes next to one one another (One checkbox for each report format) whose IsEnabled status will be predetermined.
My Current Solution
WPF
<Grid>
<TreeView Name="Views" Grid.Column ="0" ItemsSource="{Binding}" Margin="10,3,30,0" Width="230" MaxHeight="300" Height="244" VerticalAlignment="Top" BorderBrush="White">
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="False" ></Setter>
</Style>
</TreeView.ItemContainerStyle>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding OC}" >
<CheckBox IsChecked="{Binding CheckedFormat1}" IsEnabled="{Binding EnabledFormat1}" Click="CheckBoxStandardFormat1_Click" Loaded="CheckBoxStandardFormat1_Loaded" Margin="-20,0,0,0">
<CheckBox IsChecked="{Binding CheckedFormat2}" IsEnabled="{Binding EnabledFormat2}" Click="CheckBoxStandardFormat2_Click" Loaded="CheckBoxStandardFormat2_Loaded" >
<TextBlock Text="{Binding Name}" />
</CheckBox>
</CheckBox>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
OC is a data structure of reports which includes information on whether it is enabled for each report type. This code produced the following UI result:
Current Output
However it looks like each instance within the HeirachicalDataTemplate is inheriting the status of IsEnabled from the previous ones, as the greyscale changes.
Does anyone have a better solution which will allow me to bind a dynamic list of reports to a WPF output, with the formatting as described above?
Sorry in advance if this is an easy question, I am really new to C#
Update
The following is a sample of my ViewModel
[PropertyChanged.AddINotifyPropertyChangedInterface]
public class ReportsList
{
public string Name { get; set; }
public bool CheckedFormat1 { get; set; }
public bool CheckedFormat2 { get; set; }
public bool EnabledFormat1 { get; set; }
public bool EnabledFormat2 { get; set; }
public ReportsList()
{
EnabledFormat1 = true;
EnabledFormat2 = true;
}
}
and it's implementation as an ObservableCollection
public ObservableCollection<ReportsList> OC { get; set; }
There appears to be no need to use a TreeView here. You just have a list of reports. Replace TreeView with ListView or ItemsControl and replace HierarchicalDataTemplate with DataTemplate. Rather than nesting the CheckBoxes, use a StackPanel container to hold them together. And the margin of -20 wasn't helping. So you end up with:
<ItemsControl Name="Views" Grid.Column ="0" ItemsSource="{Binding OC}" Margin="10,3,30,0" Width="230" MaxHeight="300" Height="244" VerticalAlignment="Top" BorderBrush="White">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding CheckedFormat1}" IsEnabled="{Binding EnabledFormat1}" Click="CheckBoxStandardFormat1_Click" Loaded="CheckBoxStandardFormat1_Loaded" Margin="20,0,0,0"/>
<CheckBox IsChecked="{Binding CheckedFormat2}" IsEnabled="{Binding EnabledFormat2}" Click="CheckBoxStandardFormat2_Click" Loaded="CheckBoxStandardFormat2_Loaded" />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

How to set the focus in a TextBox of a ListView item?

On a UWP app (Windows 10), I am displaying a list of records in a ListView.
When I click on an item, its StackPanel is displayed (using INotifyPropertyChanged).
In the StackPanel, there is a TextBox with some data populated via binding.
I would like that the TextBox automatically receives the focus whenever the StackPanel becomes visible, but I can't find which property or event to use, and how to trigger a textBox.Focus().
Thanks for your feedback on this !
The DataTemplate:
<DataTemplate x:Key="templateList">
<StackPanel>
...
<StackPanel Visibility="{Binding IsSelected}">
<TextBox x:Name="textBox"
Text="{Binding Title, Mode=TwoWay}"/>
...
</StackPanel>
</StackPanel>
</DataTemplate>
...
The ListView:
<ListView x:Name="listView"
ItemsSource="{Binding mylist}"
ItemTemplate="{StaticResource templateList}"/>
I can suggest use Behaviors for this case. As I noticed, you use Visibility type for IsSelected property. It means that we can use DataTriggerBehavior and create our SetupFocusAction which implement IAction
public class SetupFocusAction : DependencyObject, IAction
{
public Control TargetObject
{
get { return (Control)GetValue(TargetObjectProperty); }
set { SetValue(TargetObjectProperty, value); }
}
public static readonly DependencyProperty TargetObjectProperty =
DependencyProperty.Register("TargetObject", typeof(Control), typeof(SetupFocusAction), new PropertyMetadata(0));
public object Execute(object sender, object parameter)
{
return TargetObject?.Focus(FocusState.Programmatic);
}
}
After that we can use this action in XAML:
xmlns:i="using:Microsoft.Xaml.Interactivity"
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
...
<StackPanel Visibility="{Binding IsSelected}"
Grid.Row="1">
<TextBox x:Name="textBox"
Text="{Binding Title, Mode=TwoWay}">
<i:Interaction.Behaviors>
<core:DataTriggerBehavior Binding="{Binding IsSelected}"
ComparisonCondition="Equal"
Value="Visible">
<local:SetupFocusAction TargetObject="{Binding ElementName=textBox}"/>
</core:DataTriggerBehavior>
</i:Interaction.Behaviors>
</TextBox>
</StackPanel>

Vista style ListView (GridViewRowPresenter)

I'd like to display data in ListView with different rows (different style and different content). But as soon as I try to apply a style (which suppose to change nothing) selection stops working and it's not anymore Vista style.
What am I doing wrong? Perhaps wrong approach?
<ListView ItemsSource="{Binding A}">
<ListView.View>
<GridView>
<GridViewColumn Header="B" DisplayMemberBinding="{Binding B}"/>
...
</GridView>
</ListView.View>
<!-- commenting below block will return Vista style back -->
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<GridViewRowPresenter Content="{TemplateBinding Content}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
You shouldn't change the ControlTemplate of the ListViewItem, if you want to display data in a ListView with different rows (different style and different content).
Use DataTemplate instead. You can style your rows according to the bound data type.
Assuming you have a view model like this:
public class ViewModel : INotifyPropertyChanged
{
public List<object> A { get; private set; }
public ViewModel()
{
this.A = new List<object> { Brushes.BlueViolet, 42, false };
}
}
Then, just define the DataTemplates for your items that you wish to display in the list view:
<ListView ItemsSource="{Binding A}">
<ListView.View>
<GridView>
<GridViewColumn Header="B"/>
</GridView>
</ListView.View>
<ListView.Resources>
<DataTemplate DataType="{x:Type media:Brush}">
<Rectangle Width="25" Height="25" Fill="{Binding Mode=OneWay}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type sys:Boolean}">
<CheckBox IsChecked="{Binding Mode=OneWay}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type sys:Int32}">
<TextBlock Text="{Binding Mode=OneWay}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="FontWeight" Value="Bold"/>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</ListView.Resources>
</ListView>
With this approach, you will get the list view rows that represent your data as you wish, retaining the core ListView functionality and "Vista style".
I try to keep it as general as possible so I define a simple enum for different types that each row can take:
public enum RowType { Bool, Int32 }
Now I use it in the view model for row:
public class Row: DependencyObject
{
//create a new row with the given value
//automatically set Value, Info and RowType based on the param
public Row(object val)
{
Value = val;
if (val.GetType() == typeof(bool)) RowType = WpfApplication3.RowType.Bool;
else RowType = WpfApplication3.RowType.Int32;
Info = val.ToString() + " of type " +val.GetType().ToString();
}
public RowType RowType { get; set; }
/// <summary>
/// Gets or sets a bindable value that indicates Value
/// </summary>
public object Value
{
get { return (object)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(object), typeof(Row), new PropertyMetadata(0));
/// <summary>
/// Gets or sets a bindable value that indicates Info
/// </summary>
public string Info
{
get { return (string)GetValue(InfoProperty); }
set { SetValue(InfoProperty, value); }
}
public static readonly DependencyProperty InfoProperty =
DependencyProperty.Register("Info", typeof(string), typeof(Row), new PropertyMetadata(""));
}
Now that the view model is ready I create a simple TemplateSelector which responds to RowType of the given row:
public class Selector : DataTemplateSelector
{
//Template for RowType==Bool
public DataTemplate Template1 { get; set; }
//Template for RowType==Int32
public DataTemplate Template2 { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var row = item as Row;
if (row == null) return null;
switch (row.RowType)
{
case RowType.Bool:
return Template1;
case RowType.Int32:
return Template2;
default:
return null;
}
}
}
And I use it in Xaml like this:
<Window.Resources>
<!-- selects CellTemplate for column1 (Value) based on RowType -->
<local:Selector x:Key="valueSelector">
<local:Selector.Template1>
<DataTemplate>
<CheckBox IsChecked="{Binding Value, Mode=OneWay}"/>
</DataTemplate>
</local:Selector.Template1>
<local:Selector.Template2>
<DataTemplate>
<TextBlock Text="{Binding Value, Mode=OneWay}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="FontWeight" Value="Bold"/>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</local:Selector.Template2>
</local:Selector>
<!-- selects CellTemplate for column2 (Info) based on RowType -->
<local:Selector x:Key="infoSelector">
<local:Selector.Template1>
<DataTemplate>
<Canvas Height="16">
<TextBlock Text="{Binding Info, Mode=OneWay}"
Foreground="Blue" VerticalAlignment="Top"/>
</Canvas>
</DataTemplate>
</local:Selector.Template1>
<local:Selector.Template2>
<DataTemplate>
<Canvas Height="16">
<TextBlock Text="{Binding Info, Mode=OneWay}"
VerticalAlignment="Top"/>
</Canvas>
</DataTemplate>
</local:Selector.Template2>
</local:Selector>
</Window.Resources>
<ListView ItemsSource="{Binding A}">
<ListView.View>
<GridView>
<GridViewColumn Header="Value"
CellTemplateSelector="{StaticResource valueSelector}"/>
<GridViewColumn Header="Info" Width="0"
CellTemplateSelector="{StaticResource infoSelector}"/>
</GridView>
</ListView.View>
</ListView>
This is the result:
Not that I wrote this answer based on dymanoid's answer which is accurate based upon given information.

Usercontrol in datatemplate out of sync

So I want to have multiple tabs with a usercontrol in it, depending on how many items there are in a list. so I think this shoudn t be too hard but .... I start with a new window to make a tabcontroller and bind its itemsource(of the tabcontroler to the list):
<Window x:Class="xxxxx.extraforms.frmownedchamps"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sp="clr-xxxxx.usercontrols.ucoptions"
Title="frmownedchamps" Height="593" Width="350" Loaded="Window_Loaded_1" ResizeMode="NoResize" WindowStyle="None" ShowInTaskbar="False">
<Grid>
<TabControl Name="thetabcontrol">
<TabControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<Label Content="{Binding name}" />
</StackPanel>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate DataType="{x:Type sp:ucownedchampviewer}" >
<sp:ucownedchampviewer strname="{Binding Path=name}" strcode="{Binding Path=code}" clclist="{Binding Path=list}" teller="{Binding Path=teller}" />
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</Grid>
</Window>
once the window get loaded it only does thetabcontrol.ItemsSource = settings.clclist;
the clclist is this:
public static List<clc> clclist { get; set; }
public void methodblabla()
{
foreach( xml blabla)
{
clc clctemp = new clc(xmlname, xmlcode);
clclist.Add(clctemp);
}
}
the clc class is:
public class clc
{
private static int counter = 0;
public int teller { get; set; }
public String name { get; set; }
public String code { get; set; }
public ObservableCollection<champion> list { get; set; }
public clc(String name, String code)
{
this.name = name;
this.code = code;
teller = counter;
counter++;
makelist();
}
public void makelist()
{
var bytes = Convert.FromBase64String(code);
var values = new System.Collections.BitArray(bytes);
list = new ObservableCollection<champion>();
int aantal = champions.list.Count;
int teller = 0;
int counter = 0;
for (int x = aantal; x != 0; x--)
{
if (values[x - 1] == true)
{
list.Add(champions.getchampbyid(counter + 1));
teller++;
}
counter++;
}
}
}
my usercontrol:
<UserControl x:Class="xxxxx.usercontrols.ucoptions.ucownedchampviewer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:sp="clr-namespace:xxxxx"
mc:Ignorable="d"
d:DesignHeight="564" d:DesignWidth="350" Loaded="UserControl_Loaded">
<Grid Height="624">
<Grid.Resources>
<Style x:Key="Ownedstyle" TargetType="{x:Type ListViewItem}">
<Setter Property="Background" Value="Red"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding strowned}" Value="Yes">
<Setter Property="Background" Value="Green"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<StackPanel Margin="0,0,0,12">
<StackPanel Orientation="Horizontal" Margin="5">
<TextBox Name="txtclc" Width="250" Margin="2" Text="{Binding Path=strcode ,RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />
<Button Name="btnload" Content="Save" Click="btnsave_Click" Width="55" Margin="2"/>
</StackPanel>
<Line Margin="2" />
<StackPanel Orientation="Horizontal" Margin="5" HorizontalAlignment="Stretch" Width="350">
<TextBlock VerticalAlignment="Center">Filter:</TextBlock>
<TextBox Name="txtfilter" Height="30" Grid.Column="0" TextChanged="txtfilter_TextChanged" Margin="5" Width="250" />
<Label Name="lblaantal"></Label>
</StackPanel>
<ListView Name="lsvallchamps" Grid.Column="0" Grid.Row="1" Grid.RowSpan="1" Height="410" Width="auto" ItemContainerStyle="{StaticResource Ownedstyle}" ItemsSource="{Binding Path=clclist ,RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" >
<ListView.View>
<GridView>
<GridViewColumn Width="60">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Image HorizontalAlignment="Center" VerticalAlignment="Center" Width="50" Height="50" Source="{Binding image}" Stretch="Fill"></Image>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="120" DisplayMemberBinding="{Binding name}">
<GridViewColumnHeader Content="name" Tag="name" Click="SortClick"/>
</GridViewColumn>
<GridViewColumn Width="130" DisplayMemberBinding="{Binding strroles}">
<GridViewColumnHeader Content="strroles" Tag="strroles" Click="SortClick" />
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
<Button Content="testknop" Click="Button_Click" />
<Button Content="Hide" Name="btnhide" Width="150" Height="35" Margin="5" Click="btnhide_Click"></Button>
</StackPanel>
</Grid>
</UserControl>
Sorry for so much code, but mayby better too much then too less code. The problem is that I want the button btnsave to save the txtclc.text to the code and make a new list of it, (and then the listview should be automaticly changed according to it since it is binded to it)
However once I use the code
private void btnsave_Click(object sender, RoutedEventArgs e)
{
settings.clclist[teller].code = txtclc.Text;
settings.clclist[teller].makelist();
}
It does change it! I can see it with debug.writeline that the value has changed in the clclist. BUT the listview in this tab doesn t change! ONLY if I go to an other tab, then back to the first one then it has changed with the right champions. There even is a 2nd problem. O But if I go to an other tab(usercontrol) the txtclc.text is changed as well to the first one! also the list is not updated on the usercontrol, on neither! however the makelist method should change it?
Sorry for this LONG question however I ve been googeling alot and no luck for this problem.
SOLUTION:
Replace Text="{Binding Path=strcode ,RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" with Text="{Binding Path=code}" in the usercontrol. and add INotifyPropertyChanged to the clc class, Thx to Rachel!
You have two problems here.
The first, is that your classes don't implement INotifyPropertyChanged, so the UI has no idea that it's objects have changed. Make your clc class implement this interface, and raise the PropertyChanged event when the code and name properties change so the UI knows to update.
The second problem is that by default, WPF will re-use a template if possible. For example, your TabControl is creating one instance of your UserControl, and when you switch tabs it is simply changing the DataContext behind the UserControl. If txtclc.Text is not bound to something in the DataContext, then it will not change because you are viewing the exact same TextBox regardless of which tab you are viewing. The solution is to add a property to your DataContext object to store the Text of the txtclc TextBox, and bind the property.

Categories

Resources