I have a strange issue with my binding...
Currently I'm just trying to binding a list of objects in a list view
XAML
ExtendedListView is just an extension of the basic listview.
<refresh:ExtendedListView PullToRefreshRequested="listView_InfoRefresh" IsPullToRefreshEnabled="True" ItemsSource="{Binding MyList, Mode=OneWay}" >
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock FontSize="16">
<Run x:Uid="TheChallenge" />
<Run Text="{Binding Title}"/>
<Run x:Uid="ExpireChallenge" />
</TextBlock>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</refresh:ExtendedListView>
C#
private List<Challenge> myList;
public List<Challenge> MyList
{
get { return myList; }
set
{
if (myList!= value)
{
myList= value;
RaisePropertyChanged(() => MyList);
}
}
}
The list is retrieve from a Wep Api application.
When I put a breakpoint, the list is not empty ( currently I have 3 elements in my list ), and after the binding of MyList, I am able to see the items 2 sec before they dissapear....
If someone have an idea.
Using a List and setting it every time data changes is not a good idea. Just use an ObservableCollection, set it juts once in ctor and then only add and remove items.
Related
I'm developing a WPF app using MVVM pattern with Caliburn.Micro
I have a config file that contains positions of where XAML elements should be inside of a StackPanel
# in this case RU_ELEMENT should be at the top, EN_ELEMENT second and DE_ELEMENT last
EN_ELEMENT = 1
DE_ELEMENT = 2
RU_ELEMENT = 0
This seems to be pretty basic yet I'm unable to find a way to do this. I found this thread: change the children index of stackpanel in wpf but changing it this way seems to be too complicated for what I am after. I just need to set an index of an element from a variable. I feel like there should be a much simpler way. I'm also ok with using some other, perhaps more appropriate layout panel than StackPanel.
XAML:
<!-- Language1 -->
<TextBlock Text="English" Foreground="DarkGray" FontSize="16"/>
<TextBox
VerticalAlignment="Top"
Height="150"
Text="{Binding SelectedItem.ValueEN, UpdateSourceTrigger=PropertyChanged}"
cm:Message.Attach="[Event GotFocus] = [Action FocusedTextBox('english')]" />
<!-- Language2 -->
<TextBlock Text="German" Foreground="DarkGray" FontSize="16"/>
<TextBox
VerticalAlignment="Top"
Height="150"
Text="{Binding SelectedItem.ValueDE, UpdateSourceTrigger=PropertyChanged}"
cm:Message.Attach="[Event GotFocus] = [Action FocusedTextBox('german')]" />
On a side note: I find WPF and C# in general to have much less discussions and "how to" guides than all of my previous languages (Java, Python, JS) so researching things online is usually a dead end for me. I'm not sure to why that is since C# is a very popular language but I'm really struggling with finding help online.
A solution could be to use an ItemsControl that would host the xaml elements. You can bind the items like <ItemsControl ItemsSource="{Binding ListOfItems} ...
Then you could easily sort the items in the corresponding ViewModel. Like so:
public BindableCollection<YourElement> ListOfItems {get;set;}
...
ListOfItems.Sort()
Note that YourElement class should have a comparator.
EDIT: As per request I'll explain it more detailed:
In your Xaml you have to declare a ItemsControl like so:
<ItemsControl ItemsSource="{Binding ListOfItems}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Language}" Foreground="DarkGray" FontSize="16"/>
<TextBox
VerticalAlignment="Top"
Height="150"
Text="{Binding TextValue, UpdateSourceTrigger=PropertyChanged}"
cm:Message.Attach="[Event GotFocus] = [Action FocusedTextBox($this)]" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
And in your backend you should first create a class that's going to represent your item in the ItemsControl. For example:
public Class MyItem{
public string Language {get;set;}
public string TextValue {get;set;}
}
Finally in your ViewModel you'll need to create the list of items that you bind with the ItemsControl like so:
public BindableCollection<MyItem> ListOfItems {get;set;}= new BindableCollection<MyItem>();
//here you can add them in the order that is specified by the config file
public void LoadItems(){
ListOfItems.Add(new MyItem{Language="English"});
ListOfItems.Add(new MyItem{Language="Russian"});
ListOfItems.Add(new MyItem{Language="German"});
}
public void FocusedTextBox(MyItem item){
//do here whatever you want
}
I'm having trouble simply showing the contents of my List in the ComboBox using Caliburn.micros BindableCollection. I get three blank options, but when I chose one of them I get the correct value back so I know it's working. Obviously I would also like to see what it is I'm choosing.
I've tried creating a local string and having it = myList[i] in a for loop. I've even created a random string and tried binding it to my TextBlock using the same naming convention, but I just can't get it to work. I won't add that here since it doesn't work. Hopefully one of you can nudge me in the right direction. I'm new to Caliburn, MVVM, binding, etc....
public List<string> languages = new List<string> {"ENGLISH", "SPANISH", "CHINESE"};
public BindableCollection<string> Language { get; set; }
public SettingsViewModel()
{
Language = new BindableCollection<string>();
for (int i = 0; i < languages.Count; i++)
{
Language.Add(languages[i]);
}
}
//XAML Code\
<ComboBox ItemsSource="{Binding Language}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding LanguageOptions}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
The problem lies in the following line.
<TextBlock Text="{Binding LanguageOptions}" />
The property Language is BindableCollection of string. It doesn't have a sub-property called LanguageOptions.
You could instead use the following
<ComboBox ItemsSource="{Binding Language}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Or to make it even more simpler, you could avoid the ItemTemplate. For example,
<ComboBox ItemsSource="{Binding Language}"/>
That would help you fix the Combo Box.
Hello Guys I hope yall doing great!
I have a problem with a datagrid, I want to put this in datagrid cell for example : "/100" which '100' is the quantity in stock in my database using entity framework, I want to do this so the user tap how many items he wants in a textbox besides the label/textBlock like this :
DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBox materialDesign:HintAssist.Hint="0"/>
<TextBlock Text="{Binding ElementName=productQuantityStock}" />
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
I hope you guys understand what I want to do, and please mind my bad English
In the code-behind you'll need to bind a context. The context will need a property and a field so the the value can be updated. You should also make use of a method that notifies the view that the property has been updated.
The code behind will look something like this.
public class DataContextOfView
{
private int _productQuantityStock;
// Because you'll be working with values of type int you should make it an int
public int ProductQuantityStock
{
get { return _productQuantityStock;}
set { if(_productQuantityStock != value)
{
_productQuantityStock = value
// notify that the value of the property has changed.
OnPropertyChanged(nameof(ProductQuantityStock));
}
}
}
}
The code in the view should have a reference to the property
DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBox materialDesign:HintAssist.Hint="0"/>
<TextBlock Text="{Binding ProductQuantityStock, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
I have a note application with a ListBox control, which lists all the available notes from the ObservableCollection<Note> Notes. class Note has attributes like
String Title;
bool Has_Reminder;
DateTime Reminder_Date;
What I want is that the TextBlock element, which shows the Reminder_Date, is only shown, if Has_Reminder is true. But I do not know how to access this attribute from my custom control NoteListItem. Its this.DataContext attribute is null, but the control still properly displays the Note's bound attributes handed down by the ListBox ItemsSource. How can I achieve that?
Thanks for your help.
I tried to read the attributes in the constructor, which did not work:
public NoteListItem()
{
InitializeComponent();
Note this_note = LayoutRoot.DataContext as Note; // turns out, this_note is null
if (!this_note.Has_Reminder)
Reminder_Info.Visibility = System.Windows.Visibility.Collapsed;
}
NoteListItem control
<Grid x:Name="LayoutRoot" >
<TextBlock x:Name="Title" Text="{Binding Title}" />
<TextBlock x:Name="Reminder_Date" Text="{Binding Reminder_Date}" />
</Grid>
NoteList control:
<ListBox x:Name="NoteListBox" ItemsSource="{Binding Notes}" >
<ListBox.ItemTemplate>
<DataTemplate>
<local:NoteListItem />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Do you know how to use a converter? Your converter would convert a bool to a Visibility, then you can bind the TextBlock's Visibility to Has_Reminder:
<TextBlock x:Name="Reminder_Date" Text="{Binding Reminder_Date}" Visibility="{Binding Has_Reminder, Converter={...}}"/>
This might help: http://www.jeff.wilcox.name/2008/07/visibility-type-converter/
I have a List bound to a TreeView like:
XAML:
<TreeView Name="browserTree"
BorderBrush="DarkSlateGray"
BorderThickness="1"
Grid.Row="2"
Margin="0,3,0,0"
ItemsSource="{Binding UpdateSourceTrigger=PropertyChanged}">
<TreeView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"/>
</DataTemplate>
</TreeView.ItemTemplate>
</TreeView>
C#:
browserTree.DataContext = treeList;
I update the list via:
void QueryChange(string s)
{
rCM.SetCommand(s);
treeList.Clear();
SqlDataReader sr = rCM.ExecuteReader(System.Data.CommandBehavior.Default);
while (sr.Read())
{
treeList.Add((string)sr["tree_hdr"]);
}
sr.Close();
}
The List<string> is just a placeholder at the moment for a more meaningful data class I have yet to implement. But right now I need to know why the TreeView is not updating to reflect the changes made to the list.
Try making the treelist an ObservableCollection.
Please check the type of your treeList which you set as DataContext. It has to be an ObservableCollection to reflect your collection changes in the UI
Or else for quick workaround, just set the DataContext again after you filled the List.