I have a table named Groups in my Database as follows:
Groups
|--GroupID
|--GroupName
|--ParentID
|--NatureOfGroupID
|--EffectID
Here is the relationship diagram for above table:
I have a combobox in a window in which I have two columns. Here is the xaml:
<ComboBox ItemsSource="{Binding DataContext.GroupNamesWithCorrespondingEffects, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Page}}}"
SelectedValue="{Binding ParentID}" SelectedValuePath="GroupID">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding GroupName}" Width="200" />
<TextBlock Text="{Binding CorrespondingEffect}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Actually i want to show GroupName and its corresponding Effect but when user selects any Item then I want to get SelectedValue as ParentID.
Here is the implementation of GroupNameWithCorrespondingEffect.cs
public class GroupNameWithCorrespondingEffect : MainViewModel
{
private string _groupName;
public string GroupName
{
get
{
return _groupName;
}
set
{
_groupName = value;
OnPropertyChanged("GroupName");
}
}
private string _correspondingEffect;
public string CorrespondingEffect
{
get
{
return _correspondingEffect;
}
set
{
_correspondingEffect = value;
OnPropertyChanged("CorrespondingEffect");
}
}
}
Here is the code for groupsViewModel.cs
public class GroupsViewModel : MainViewModel
{
public GroupsViewModel()
{
using (Entities db = new Entities())
{
GroupNamesWithCorrespondingEffects = (from g in db.Groups
select new GroupNameWithCorrespondingEffect
{
GroupName = g.GroupName,
CorrespondingEffect = g.Master_Effects.Effect
}).ToList();
NaturesOfGroup = (from m in db.Master_NatureOfGroup
select m).ToList();
}
SaveChangesCommand = new RelayCommand(SaveGroup);
CurrentGroup = new Group();
}
private Group _currentGroup;
public Group CurrentGroup
{
get
{
return _currentGroup;
}
set
{
_currentGroup = value;
OnPropertyChanged("CurrentGroup");
}
}
private List<GroupNameWithCorrespondingEffect> _groupNamesWithCorrespondingEffects;
public List<GroupNameWithCorrespondingEffect> GroupNamesWithCorrespondingEffects
{
get
{
return _groupNamesWithCorrespondingEffects;
}
set
{
_groupNamesWithCorrespondingEffects = value;
OnPropertyChanged("GroupNamesWithCorrespondingEffects");
}
}
private List<Master_NatureOfGroup> _naturesOfGroup;
public List<Master_NatureOfGroup> NaturesOfGroup
{
get
{
return _naturesOfGroup;
}
set
{
_naturesOfGroup = value;
OnPropertyChanged("NaturesOfGroup");
}
}
public ICommand SaveChangesCommand { get; set; }
private void SaveGroup(object obj)
{
Group cGroup = new Group()
{
GroupName = CurrentGroup.GroupName,
**ParentID = CurrentGroup.ParentID,**
NatureOfGroupID = CurrentGroup.NatureOfGroupID,
EffectID = CurrentGroup.EffectID
};
using (Entities db = new Entities())
{
db.Groups.Add(cGroup);
db.SaveChanges();
GroupNamesWithCorrespondingEffects = (from g in db.Groups
select new GroupNameWithCorrespondingEffect
{
GroupName = g.GroupName,
CorrespondingEffect = g.Master_Effects.Effect
}).ToList();
}
}
}
When I debug and put a breakpoint on the line marked with ** .... ** I always get CurrentGroup.ParentID = null.
Update:
<Page.DataContext>
<vm:GroupsViewModel />
</Page.DataContext>
<Grid DataContext="{Binding CurrentGroup}">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="0.6*" />
<ColumnDefinition Width="0.6*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="1" Grid.Column="1" Text="Name" HorizontalAlignment="Left"/>
<TextBlock Grid.Row="1" Grid.Column="1" Text=" : " HorizontalAlignment="Right"/>
<TextBox Grid.Row="1" Grid.Column="2" Grid.ColumnSpan="2" Text="{Binding GroupName}"/>
<TextBlock Grid.Row="2" Grid.Column="1" Text="Under" HorizontalAlignment="Left"/>
<TextBlock Grid.Row="2" Grid.Column="1" Text=" : " HorizontalAlignment="Right"/>
<ComboBox x:Name="cbUnder" Grid.Row="2" Grid.Column="2" Grid.ColumnSpan="2"
ItemsSource="{Binding DataContext.GroupNamesWithCorrespondingEffects, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Page}}}"
SelectedValue="{Binding ParentID}" SelectedValuePath="GroupID">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding GroupName}" Width="200" />
<TextBlock Text="{Binding CorrespondingEffect}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBlock Grid.Row="3" Grid.Column="1" Text="Nature of Group" HorizontalAlignment="Left" Visibility="{Binding Visibility, ElementName=cbNature}"/>
<TextBlock Grid.Row="3" Grid.Column="1" Text=" : " HorizontalAlignment="Right" Visibility="{Binding Visibility, ElementName=cbNature}"/>
<ComboBox x:Name="cbNature" Grid.Row="3" Grid.Column="2" Visibility="{Binding SelectedIndex, Converter={StaticResource selectedIndexToVisibilityConverter}, ElementName=cbUnder}"
ItemsSource="{Binding DataContext.NaturesOfGroup, RelativeSource={RelativeSource AncestorType={x:Type Page}}}" DisplayMemberPath="Nature"
SelectedValue="{Binding NatureOfGroupID}" SelectedValuePath="NatureOfGroupID"/>
<StackPanel Grid.Row="5" Grid.Column="4" Orientation="Horizontal">
<Button Content="Save" Command="{Binding DataContext.SaveChangesCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Page}}}"/>
</StackPanel>
</Grid>
I can see two issues in your code.
First of all you mentioned
Actually i want to show GroupName and its corresponding Effect but
when user selects any Item then I want to get SelectedValue as
ParentID.
But in combobox declaration, you set SelectedValuePath="GroupID". It should be set to ParentID - SelectedValuePath="ParentID".
Second, even if you set SelectedValuePath to ParentID, it won't work since combobox ItemsSource is a list of GroupNameWithCorrespondingEffect which doesn't have any property ParentID in it.
For SelectedValuePath to work underlying model class should have that property, so create a property and filled it from database like other two properties.
GroupNamesWithCorrespondingEffects = (from g in db.Groups
select new GroupNameWithCorrespondingEffect
{
GroupName = g.GroupName,
CorrespondingEffect = g.Master_Effects.Effect,
ParentID = g.ParentId
}).ToList();
So, for your solution to work, you have to fix both these issues.
Related
I am trying to make a button in a viewmodel recognize that a radio button in another view model (a UserControl that is activated on the first viewmodel) has been selected, thus enabling the button in the first viewmodel.
I have a UserControl AlbumsDisplayViewModel within my base view model BaseViewModel.
In BaseView XAML There's a button (OpenAlbum) which is supposed to be enabled when a radio button on the AlbumsDisplayView is selected (see CanOpenAlbum).
BaseView XAML:
<Canvas x:Name="cnvsInputWrapper" Background="LightGray"
Grid.Column="4" Grid.Row="1" Grid.RowSpan="4"
Margin="5">
<Canvas.OpacityMask>
<VisualBrush Visual="{Binding ElementName=maskRoundEdges}" />
</Canvas.OpacityMask>
<DockPanel Margin="15, 25">
<ContentControl x:Name="ActiveItem" />
</DockPanel>
</Canvas>
<!-- Action Buttons section -->
<Grid Grid.Row="3" Grid.Column="1" Grid.RowSpan="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="12" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="12" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="12" />
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
<RowDefinition Height="*" />
<RowDefinition Height="12" />
</Grid.RowDefinitions>
<Button Grid.Row="1" Grid.Column="1" x:Name="OpenAlbum"
IsEnabled="{Binding CanOpenAlbum}">
<StackPanel Orientation="Vertical">
<TextBlock>Open</TextBlock>
<TextBlock>Album</TextBlock>
</StackPanel>
</Button>
</Grid>
BaseViewModel C#:
public class BaseViewModel : Conductor<object>
{
private AlbumsDisplayViewModel m_vmAlbumsDisplay; // Initialized in another function.
public BaseViewModel()
{
}
public bool CanOpenAlbum() => (m_vmAlbumsDisplay != null) && (m_vmAlbumsDisplay.GetSelectedAlbum() != null);
public void OpenAlbum()
{
AlbumModel album = m_vmAlbumsDisplay.GetSelectedAlbum();
//ActivateItem(/*albumViewModel(album)*/);
}
}
AlbumsDisplayView XAML:
<ItemsControl x:Name="Albums" FlowDirection="LeftToRight"
Margin="10, 0">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type vms:AlbumViewModel}">
<StackPanel Orientation="Horizontal" Margin="0, 5">
<RadioButton GroupName="rdbtnAlbums"
IsChecked="{Binding IsSelected}" />
<!-- Album Details -->
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
AlbumsDisplayViewModel C#:
class AlbumsDisplayViewModel : Screen
{
private ObservableCollection<AlbumViewModel> m_albums;
public AlbumsDisplayViewModel()
{
}
public ObservableCollection<AlbumViewModel> Albums
{
get { return m_albums; }
set
{
m_albums = value;
NotifyOfPropertyChange(() => Albums);
}
}
public AlbumModel GetSelectedAlbum()
{
AlbumModel res = null;
foreach (var vmAlbum in Albums)
{
if (vmAlbum.IsSelected)
{
res = vmAlbum.Album;
break;
}
}
return res;
}
}
And last, AlbumViewModel C#:
class AlbumViewModel : Screen
{
private AlbumModel m_albumModel;
private bool m_isSelected;
public AlbumViewModel(AlbumModel albumModel)
{
m_albumModel = albumModel;
}
public AlbumModel Album
{
get { return m_albumModel; }
set
{
m_albumModel = value;
NotifyOfPropertyChange(() => Album);
}
}
public bool IsSelected
{
get { return m_isSelected; }
set
{
m_isSelected = value;
NotifyOfPropertyChange(() => IsSelected);
}
}
}
I expected that when IsSelected in AlbumViewModel is changed (when the user selects a radio button), the OpenAlbum button will be enabled, because CanOpenAlbum will return true, but I have realized that CanOpenAlbum wasn't even called for some reason. What do I need to do so CanOpenAlbum will be notified to be called whenever a radio button is selected?
After searching for an answer for a long time, I decided that it will be better to search for a better solution, instead of an answer. I've discovered that a ListBox element has a SelectedItem property, which eliminates the need for radio buttons.
Eventually, I replaced the ItemsControl with a ListBox, and I;m happy with the results.
AlbumDisplayView XAML (only this has changed):
<ScrollViewer x:Name="Scroller" Height="300"
FlowDirection="RightToLeft">
<ListBox x:Name="Albums" FlowDirection="LeftToRight"
Background="Transparent" Margin="10, 0"
BorderThickness="0" SelectedItem="{Binding SelectedAlbum}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type vms:AlbumViewModel}">
<StackPanel Orientation="Horizontal" Margin="0, 5">
<!-- Album Details -->
<StackPanel Orientation="Vertical">
<StackPanel Grid.Row="1" Grid.Column="1"
Orientation="Horizontal" Margin="12, 0">
<TextBlock Text="{Binding Album.Name}" />
<TextBlock Text=" - User#" />
<TextBlock Text="{Binding Album.OwnerID}" />
</StackPanel>
<TextBlock Text="{Binding Album.CreationDate}"
FontSize="12" Margin="12, 0" />
</StackPanel>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListBox>
</ScrollViewer>
I'm learning wpf through mvvm.
My application consist of below logic.
Form which has a button that will add a selected components horizontally from Itemcontrol like textbox, combobox and rich textbox and a button whenever the button is clicked.
When the add button is clicked the specified set of components will be added in the line information dynamically.
2) Data will be inserted into the table after pressing the add info button.
3) The issue is after clicking the add info button, the components in the itemscontrol should be readonly. This is the place I'm struggling as of now.
Model.cs:
public class textboxModel
{
public string Text { get; set; }
public string lblText { get; set; }
public string isactive { get; set; }
public bool txtboxreadonly { get; set; }
}
public class ButtonDataModel
{
public string Content { get; set; }
public ICommand Command { get; set; }
public string column { get; set; }
public string isactive { get; set; }
public bool buttreadonly { get; set; }
}
ViewModel.cs:
public class viewmodel : notifyproperties
{
public Relaycommand Status { get; set; }
public Relaycommand AddCommand { get; set; }
public labelconversionOnPauseButtonclick pauseclick = new labelconversionOnPauseButtonclick();
public auditinformation auditid = new auditinformation();
public ButtonDataModel bdm = new ButtonDataModel();
public auditinformation adt
{
get { return auditid; }
set
{
if (value != auditid)
{
auditid = value;
OnPropertyChanged("adt");
}
}
}
public labelconversionOnPauseButtonclick res
{
get { return pauseclick; }
set
{
if (value != pauseclick)
{
pauseclick = value;
OnPropertyChanged("res");
}
}
}
public viewmodel()
{
Status = new Relaycommand(pauseclick.Statusdata);
AddCommand = new Relaycommand(o => auditid.addcommand());
}
}
public class auditinformation : notifyproperties
{
public Relaycommand Command { get; set; }
private string _lines;
public string Lines
{
get { return this._lines; }
set
{
this._lines = value;
this.OnPropertyChanged("Lines");
}
}
private readonly ObservableCollection<ButtonDataModel> _MyDatabutton = new ObservableCollection<ButtonDataModel>();
public ObservableCollection<ButtonDataModel> MyData { get { return _MyDatabutton; } }
private readonly ObservableCollection<textboxModel> _MyDatatxtbox = new ObservableCollection<textboxModel>();
public ObservableCollection<textboxModel> MyDatatxtbox { get { return _MyDatatxtbox; } }
private readonly ObservableCollection<LabelDataModel> _MyDataLabel = new ObservableCollection<LabelDataModel>();
public ObservableCollection<LabelDataModel> MyDataLabel { get { return _MyDataLabel; } }
public void addcommand()
{
int num= 1;
for (int i = 0; i < num; i++)
{
MyDatatxtbox.Add(new textboxModel
{
isactive = "1",
});
MyData.Add(new ButtonDataModel
{
Command = new Relaycommand(o => search()),
Content = "Add info",
isactive = "1",
});
}
}
public void search( )
{
var asss = MyDatatxtbox.Where(a=> a.isactive == "1").Select(a => a.Text);
var itemstoremove = MyDatatxtbox.Where(i => i.isactive == "1").ToList();
foreach (var s in asss)
{
foreach (var a in itemstoremove)
{
if (a.isactive == "1")
{
MessageBox.Show(s);
buttreadonly = true;
}
}
}
// var itemstoremove = MyDatatxtbox.Where(i => i.isactive == "1").ToList();
foreach(var a in itemstoremove)
{
a.isactive = "0";
}
//foreach (var a in itemstoremove)
//{
// a.txtboxreadonly = true;
//}
// var itemstoremovebutton = MyData.Where(i => i.isactive == "1").ToList();
// foreach (var a in itemstoremovebutton)
// {
//// MyData.Remove(a);
// a.isactive = "0";
// }
}
}
window.xaml:
<GroupBox Header="Audit Information" Grid.Row="1">
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="0" Text="Member ID"></TextBlock>
<TextBox HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="1" Width="85" ></TextBox>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="2" Text="Claim Number"></TextBlock>
<TextBox HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="3" Width="85" ></TextBox>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="4" Text="Date Audited"></TextBlock>
<TextBox HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="5" Width="85" ></TextBox>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="6" Text="Query ID"></TextBlock>
<TextBox HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="7" Width="85" ></TextBox>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="8" Text="Audit ID"></TextBlock>
<TextBox HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="9" Width="85" ></TextBox>
<Button HorizontalAlignment="Center" VerticalAlignment="Center" Width="85" Height="25" Command="{Binding AddCommand}" Content="Add" Grid.Column="10"></Button>
</Grid>
</GroupBox>
<GroupBox Grid.Row="2" Margin="0,0,0,0" Header="Line Information" >
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="3.2*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="1.8*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Height="22" Grid.Column="0">
<Label HorizontalAlignment="Center" Content="DOS" />
</StackPanel>
<ItemsControl Grid.Column="0" Grid.Row="1" ItemsSource="{Binding adt.MyDatatxtbox}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,50">
<TextBox IsReadOnly="{Binding txtboxreadonly}" Text="{Binding Text, Mode=TwoWay}" Height="25" Width="85" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<StackPanel Height="22" Grid.Column="1">
<Label HorizontalAlignment="Center" Content="CPT" />
</StackPanel>
<ItemsControl Grid.Column="1" Grid.Row="1" ItemsSource="{Binding adt.MyDatatxtbox}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,50">
<TextBox IsReadOnly="{Binding txtboxreadonly}" Margin="0,0,30,0" Text="{Binding Text, Mode=TwoWay}" Height="25" Width="85" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<StackPanel Height="22" Grid.Column="2">
<Label HorizontalAlignment="Right" Content="Open-close Modifier" Margin="0,0,-17,0" Width="121" />
</StackPanel>
<ItemsControl Grid.Column="2" Grid.Row="1" ItemsSource="{Binding adt.MyDatatxtbox}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,50">
<TextBox IsReadOnly="{Binding txtboxreadonly}" Margin="0,0,30,0" Text="{Binding Text, Mode=TwoWay}" Height="25" Width="85" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<StackPanel Height="22" Grid.Column="3">
<Label HorizontalAlignment="Center" Content="Comments" />
</StackPanel>
<ItemsControl Grid.Column="3" Grid.Row="1" ItemsSource="{Binding adt.MyDatatxtbox}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,10">
<RichTextBox IsReadOnly="{Binding txtboxreadonly}" Margin="0,0,0,0" Height="65" Width="425" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<StackPanel Height="22" Grid.Column="4">
<Label HorizontalAlignment="Center" Content="Line Status" />
</StackPanel>
<ItemsControl Grid.Column="4" Grid.Row="1" ItemsSource="{Binding adt.MyDatatxtbox}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="10,0,0,50">
<ComboBox IsEnabled= "{Binding txtboxreadonly}" Margin="0,0,0,0" Height="25" Width="95" >
<ComboBoxItem Content="Coffie"></ComboBoxItem>
<ComboBoxItem Content="Tea"></ComboBoxItem>
</ComboBox>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<StackPanel Height="22" Grid.Column="5">
<Label HorizontalAlignment="Center" Content="Additional Comments" />
</StackPanel>
<ItemsControl Grid.Column="5" Grid.Row="1" ItemsSource="{Binding adt.MyDatatxtbox}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,10">
<RichTextBox IsReadOnly="{Binding txtboxreadonly}" Margin="0,0,0,0" Height="65" Width="425" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<ItemsControl Grid.Column="6" Grid.Row="1" ItemsSource="{Binding adt.MyData}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,50">
<Button Margin="0,0,0,0" Height="25" Width="55" Content="{Binding Content}" Command="{Binding Command}" >
</Button>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</ScrollViewer>
</GroupBox>
</Grid>
</Grid>
</TabItem>
</TabControl>
So the question is how to disable/readonly the Line Information ,textbox and cpt on add info button click.
Dirty way would be adding a "global" bool property in your ViewModel and binding it to your Controls IsEnabled/ReadOnly Properties.
I have class
public class Clip
{
public string ID { get; set; }
public string Name { get; set; }
public int? Duration { get; set; }
}
And ObservableCollection
public ObservableCollection<Clip> _clipsFound;
public ObservableCollection<Clip> collection
{
get { return _clipsFound; }
set
{
_clipsFound = value;
OnPropertyChanged();
}
}
OnPropertyChanged() is invoked when I do
_clipsFound = collection
I want binding data from collection to ListBox with three columns: ID, Name, Duration
Initialize
ID = id;
collection = new ObservableCollection<Clip>();
_clipsFound = collection;
_clipsFound.Clear();
ICollection<Clip> ClipF = await Service.GetClips(ID);
ICollection<Clip> Clipcol = ClipF;
collection = new ObservableCollection<Clip>(Clipcol);
I try do this, but it doesn't work
<ListBox Grid.Row="2" ItemsSource="{Binding collection}" BorderBrush="Transparent" >
<ListBox.ItemTemplate>
<DataTemplate DataType="ui:Clip">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Text="{Binding Title}"
VerticalAlignment="Center"
HorizontalAlignment="Left"
TextTrimming="CharacterEllipsis"
Foreground="#FF4F4F4F"
FontSize="12"
Margin="55 0 0 0"/>
<TextBlock Grid.Column="1"
Margin="0 0 45 0"
Text="{Binding Duration}"
VerticalAlignment="Center"
HorizontalAlignment="Right"
FontSize="11"
Foreground="#FF4F4F4F"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
What did I do wrong?
You cannot send data from viewmodel to view without setting DataContext. DataContext is like channel or bridge between ViewModel and View.
This code sets DataContext:
<Window.DataContext>
<vm:MainWindowViewModel />
</Window.DataContext>
Let's see work example:
Your ViewModel:
public class MainWindowViewModel
{
publicMainWindowViewModel
{
LoadData();
}
private void LoadData()
{
_clipsFound=new ObservableCollection<Clip>();
for(int startIndex=0; startIndex<10; startIndex++)
{
collection.Add(new Clip(){ID=startIndex, Name="Bob", Duration=startIndex++});
}
}
public ObservableCollection<Clip> _clipsFound;
public ObservableCollection<Clip> collection
{
get
{
return _clipsFound;
}
set
{
_clipsFound = value;
}
}
}
Your XAML:
<Window x:Class="DataGridSelectedItemsWpfApplication.MainWindow"
...The code omitted for the brevity...
xmlns:vm="clr-namespace:DataGridSelectedItemsWpfApplication.ViewModel"
Title="MainWindow" WindowStartupLocation="CenterScreen" Height="550" Width="525">
<Window.DataContext>
<vm:MainWindowViewModel />
</Window.DataContext>
<ListBox Grid.Row="2" ItemsSource="{Binding collection}" BorderBrush="Transparent" >
<ListBox.ItemTemplate>
<DataTemplate DataType="ui:Clip">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding ID}" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="11" Margin="2" Foreground="#FF4F4F4F"/>
<TextBlock Grid.Column="1" Margin="2" Text="{Binding Name}" VerticalAlignment="Center" HorizontalAlignment="Center" TextTrimming="CharacterEllipsis" Foreground="#FF4F4F4F" FontSize="12"/>
<TextBlock Grid.Column="2" Margin="2" Text="{Binding Duration}" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="11" Foreground="#FF4F4F4F"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Window>
There are many ways to set DataContext.
I am trying to bind a dictionary to two textblocks in a listview. The listview ItemsSource binding is defined in the code behind and the text blocks content is in the XAML.
I am able to display the items but they are displayed with square brackets around each row like [stringA, stringB]. However, this format will not work. The latest code that I tried was by setting the Key and Value which did not work was:
XAML:
<ListView Name="lvListLogs"
Margin="0,10,0,0">
<ListView.ItemTemplate>
<DataTemplate x:Name="ListItemTemplate">
<Grid Margin="5,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="122"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition MaxHeight="104"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock x:Name="tb_PointName" Grid.Column="1"
Text="{Binding Key}"
Margin="10,0,0,0" FontSize="40"
TextWrapping="Wrap"
MaxHeight="72"
Foreground="#FFFE5815" />
<TextBlock x:Name="tb_PointValue" Grid.Column="1"
Text="{Binding Value}"
Margin="10,0,0,0" FontSize="40"
TextWrapping="Wrap"
MaxHeight="72"
Foreground="#FFFE5815" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
C# (abridged for clarity):
public Dictionary<string, string> mydict2 { get; set; }
mydict2 = new Dictionary<string, string>();
if (item != null)
{
var props = item.GetType().GetRuntimeProperties();
foreach (var prop in props)
{
foreach (var itm in group1.Items.Where(x => x.UniqueId == prop.Name))
{
var _Title = prop.Name;
var _Value = prop.GetValue(item, null);
string propertyValue;
string propertyName;
propertyValue = Convert.ToString(_Value);
propertyName = _Title;
mydict2.Add(_Title, propertyValue);
}
}
//binding here
lvListLogs.ItemsSource = mydict2;
}
Any assistance would be appreciated.
Your code works fine, the problem is you set the same Grid.Column for both TextBlocks. The first column index should be zero:
<TextBlock x:Name="tb_PointName" Grid.Column="0" ...
To achieve the required binding, instead of the Dictionary I used an ObservableCollection with the class and constructor.
To databind the listview (xaml) to ObservableCollection:
Create the Class with Constructor
public class PointInfoClass
{
public string PointName { get; set; }
public string PointValue { get; set; }
public PointInfoClass(string pointname, string pointvalue)
{
PointName = pointname;
PointValue = pointvalue;
}
}
Create collection of the PointInfoClass
public ObservableCollection<PointInfoClass> PointInfo
{
get
{
return returnPointInfo;
}
}
Instantiate the collection
ObservableCollection<PointInfoClass> returnPointInfo = new ObservableCollection<PointInfoClass>();
Add item to collection
returnPointInfo.Add(new PointInfoClass(string1, string2));
Databind to the ObservableCollection name.
The xaml code:
<ListView
Grid.Row="1"
ItemsSource="{Binding PointInfo}"
IsItemClickEnabled="True"
ItemClick="ItemView_ItemClick"
Margin="19,0.5,22,-0.333"
x:Name="lvPointInfo"
Background="White">
<ListView.ItemTemplate>
<DataTemplate >
<Grid Margin="0,0,0,20">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="270"/>
<ColumnDefinition Width="60"/>
</Grid.ColumnDefinitions>
<StackPanel Orientation="Vertical" Grid.Column="1" VerticalAlignment="Top">
<TextBlock x:Name="tb_PointSubTitle" Grid.Column="1"
Text="{Binding PointName}"
Margin="10,0,0,0" FontSize="20"
TextWrapping="Wrap"
MaxHeight="72"
Foreground="#FF5B5B5B"
/>
</StackPanel>
<StackPanel Orientation="Vertical" Grid.Column="2" VerticalAlignment="Top" HorizontalAlignment="Right">
<TextBlock x:Name="tb_PointValue"
Grid.Column="1"
Text="{Binding PointValue}"
Margin="0,5,0,0" FontSize="20"
HorizontalAlignment="Right"
TextWrapping="Wrap"
FontWeight="Normal"
Foreground="Black" />
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Set the DataContext of the ListView
lvPointInfo.DataContext = this;
This code is edited for clarity.
the error happen when click on the root of the treeview.
how to fix this problem.
I upload this project on 2shared.com
this project on 2shared.com
download here
this is my XAML
<Window x:Class="ExTreeview.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ExTreeview"
Title="MainWindow" Height="550" Width="525">
<Window.Resources>
<HierarchicalDataTemplate x:Key="LocationTemplate" ItemsSource="{Binding SubLocation}">
<StackPanel>
<Label Content="{Binding name}"/>
</StackPanel>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type local:MyLocation}">
<TextBlock>for root</TextBlock>
</DataTemplate>
<DataTemplate DataType="{x:Type local:house}" > <!-- object from house class use this DataTemplate-->
<StackPanel Margin="0,70,0,0">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="60" />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" VerticalAlignment="Center"> ชื่อ</TextBlock>
<TextBlock Grid.Row="1" Grid.Column="0">
ความจุ(ตัว)
</TextBlock>
<TextBlock Grid.Row="2" Grid.Column="0"> สถานะ</TextBlock>
<TextBlock Grid.Row="3" Grid.Column="0"> หมายเหตุ</TextBlock>
<TextBox Grid.Column="1" Grid.Row="0" Height="20" x:Name="txtName" Text="{Binding Path=name}"></TextBox>
<TextBox Grid.Column="1" Grid.Row="1" Width="70" HorizontalAlignment="Left" x:Name="txtCapacity" Text="{Binding Path=capacity}">
</TextBox>
<ComboBox Grid.Column="1" Grid.Row="2" Width="70" HorizontalAlignment="Left" x:Name="cmbStatus" >
<ComboBoxItem Content="{Binding status}" />
</ComboBox>
<TextBox Grid.Column="1" Grid.Row="3" x:Name="txtComment" Text="{Binding Path=comment}"></TextBox>
</Grid>
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Location}" > <!-- object from Location class use this DataTemplate-->
<StackPanel Margin="0,70,0,0" >
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="60" />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" VerticalAlignment="Center"> ชื่อ</TextBlock>
<TextBlock Grid.Row="1" Grid.Column="0"> สถานะ</TextBlock>
<TextBlock Grid.Row="2" Grid.Column="0"> หมายเหตุ</TextBlock>
<TextBox Grid.Column="1" Grid.Row="0" Height="20" x:Name="txtName" Text="{Binding Path=name}"></TextBox>
<ComboBox Grid.Column="1" Grid.Row="1" Width="70" HorizontalAlignment="Left" x:Name="cmbStatus" >
<ComboBoxItem Content="{Binding status}" />
</ComboBox>
<TextBox Grid.Column="1" Grid.Row="2" x:Name="txtComment" Text="{Binding Path=comment}"></TextBox>
</Grid>
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type local:zone}"> <!-- object from zone class use this DataTemplate-->
<StackPanel Margin="0,70,0,0" DataContext="{Binding ElementName=TreeView1, Path=SelectedItem}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="60" />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" VerticalAlignment="Center"> ชื่อ</TextBlock>
<TextBlock Grid.Row="1" Grid.Column="0"> สถานะ</TextBlock>
<TextBlock Grid.Row="2" Grid.Column="0"> หมายเหตุ</TextBlock>
<TextBox Grid.Column="1" Grid.Row="0" Height="20" x:Name="txtName" Text="{Binding Path=name}"></TextBox>
<ComboBox Grid.Column="1" Grid.Row="1" Width="70" HorizontalAlignment="Left" x:Name="cmbStatus" >
<ComboBoxItem Content="{Binding status}" />
</ComboBox>
<TextBox Grid.Column="1" Grid.Row="2" x:Name="txtComment" Text="{Binding Path=comment}"></TextBox>
</Grid>
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="450" />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TreeView Grid.Column="0" Grid.Row="0" Name="TreeView1" >
<TreeViewItem Header="ทั้งหมด" Name="TreeviewRootNode" ItemTemplate="{DynamicResource LocationTemplate}">
</TreeViewItem>
</TreeView>
<StackPanel Grid.Column="0" Grid.Row="1" Grid.ColumnSpan="2" Orientation="Horizontal" HorizontalAlignment="Right">
<Button Content="นำไปใช้งาน" Height="30" Width="80" />
<Button Content="ยกเลิก" Height="30" Margin="15" Width="50" Click="Button_Click" />
</StackPanel>
<ContentControl Content="{Binding ElementName=TreeView1, Path=SelectedItem}" Grid.Column="1" Grid.Row="0">
</ContentControl>
</Grid>
here cs file of the xaml
namespace ExTreeview
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
MyLocation locationList = new MyLocation();
Location location1 = new Location();
location1.name = "ฟาร์มชัยภูมิ";
location1.id = "01";
location1.comment = "คอมเม้น";
location1.status = "ใช้งาน";
location1.SubLocation = new List<zone>();
List<house> sub1 = new List<house>();
sub1.Add(new house() { name = "โรงเรือน ช11", capacity = "50,000", status = "ใช้งาน", comment = "comment" });
sub1.Add(new house() { name = "โรงเรือน ช12", capacity = "30,000", status = "ใช้งาน", comment = "comment" });
location1.SubLocation.Add(new zone() { name = "โซน ช1", SubLocation = sub1, status = "ใช้งาน", comment = "comment" });
List<house> sub2 = new List<house>();
sub2.Add(new house() { name = "โรงเรือน ช21", capacity = "80,000", status = "ใช้งาน", comment = "comment" });
sub2.Add(new house() { name = "โรงเรือน ช22", capacity = "50,000", status = "ใช้งาน", comment = "comment" });
location1.SubLocation.Add(new zone() { name = "โซน ช2", SubLocation = sub2, status = "ใช้งาน", comment = "comment" });
Location location2 = new Location();
location2.name = "ฟาร์มนครนายก";
location2.SubLocation = new List<zone>();
List<house> sub3 = new List<house>();
List<house> sub4 = new List<house>();
List<house> sub6 = new List<house>();
sub3.Add(new house() { name = "โรงเรือนย่อย นย1", capacity = "50,000", status = "ใช้งาน", comment = "comment" });
sub3.Add(new house() { name = "โรงเรือนย่อย นย2", capacity = "60,000", status = "ใช้งาน", comment = "comment" });
sub4.Add(new house() { name = "โซนย่อย นย1", SubLocation = sub3, status = "ใช้งาน", comment = "comment" });
sub4.Add(new house() { name = "โรงเรือน น11", capacity = "50,000", status = "ใช้งาน", comment = "comment" });
sub4.Add(new house() { name = "โรงเรือน น12", capacity = "40,000", status = "ใช้งาน", comment = "comment" });
location2.SubLocation.Add(new zone() { name = "โซน น1", SubLocation=sub4, status = "ใช้งาน", comment = "comment" });
List<house> sub5 = new List<house>();
sub5.Add(new house() { name = "โรงเรือน น21", capacity = "30,000", status = "ใช้งาน", comment = "comment" });
location2.SubLocation.Add(new zone() { name = "โซน น2", SubLocation = sub5, status = "ใช้งาน", comment = "comment" });
locationList.Add(location1);
locationList.Add(location2);
TreeviewRootNode.ItemsSource = locationList;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}
}
here Location class
namespace ExTreeview
{
public class Location
{
public string name { set; get; }
public string id { set; get; }
public string status { set; get; }
public string comment { set; get; }
public List<zone> SubLocation { set; get; }
public override string ToString()
{
return (this.name);
}
}
public class zone : Location
{
public string capacity { set; get; }
public List<house> SubLocation { set; get; }
public List<house> SubLocationZ { set; get; }
}
public class house : Location
{
public string capacity { set; get; }
public List<house> SubLocation { set; get; }
}
public class MyLocation : List<Location> { }
}
help me please.
I'm try to fix this over 2 day.
thank for help me.
Your problem is caused by the explicit root TreeViewItem and by the ContentControl which is bound to the TreeView's SelectedItem.
When you select the root, the binding tries to make the treeview's root item (which is TreeViewItem) as a logical child of the ContentControl. Because in WPF an element can be only a logical child of one another element and because your root item is already the child of the treeview you get the exception:
Specified element is already the logical child of another element.
Disconnect it first.
If you select any other node it works because in these cases the SelectedItem is not a TreeViewItem but an instance of your Location class.
To make it work you should create your root node in code instead of XAML:
public class Root
{
public string name { get; set; }
public MyLocation Locations { get; set; }
}
Instead of TreeviewRootNode.ItemsSource = locationList;:
var root = new Root() { Locations = locationList, name = "ทั้งหมด" };
TreeView1.ItemsSource = new List<Root> { root };
XAML:
<TreeView Grid.Column="0" Grid.Row="0" Name="TreeView1"
ItemTemplate="{DynamicResource RootTemplate}" />
DataTemplates:
<HierarchicalDataTemplate x:Key="RootTemplate" ItemsSource="{Binding Locations}"
ItemTemplate="{StaticResource LocationTemplate}">
<StackPanel>
<Label Content="{Binding name}"/>
</StackPanel>
</HierarchicalDataTemplate>
<!--Empty DataTemplate to display the root when selected-->
<DataTemplate DataType="{x:Type local:Root}" />