How to relate two binding in wpf in c# - c#

I have a solution in C# with two proyects. The first proyect calls to the second and uses a value of its binding (EstadoVisibleTeclado).
But when I want to use this value whitin a label, It does not appeare.
For example, in the first proyect:
<Label Grid.Column="0" Visibility="{Binding EstadoVisibleTeclado}" Grid.Row="2" HorizontalAlignment="Left" VerticalAlignment="Center" FontWeight="Bold" FontSize="30" Width="AUTO" Content="Dirección" Margin="0,8,0,9"/>
In the second proyect I am writing the property to use in the DataContext of this way:
public String EstadoVisibleTeclado
{
get { return _estadoVisibleTeclado; }
set
{
_estadoVisibleTeclado = value;
this.OnPropertyChanged("EstadoVisibleTeclado");
}
}
and in the constructor of this way:
public Teclado()
{
InitializeComponent();
EstadoVisibleTeclado = "Collapsed";
this.DataContext = this;
}
Someone knows ¿how to shared the binding between proyects?.
someone like this:
Visibility="{PROYECT2.NAMEXAML.Binding EstadoVisibleTeclado}"
Regards.

Estadivisibleeclado should not be a string.

Related

Databinding for Instances of class objects

To preface this I am new to WPF, XAML and C#
I have been looking for that last two days now for a method to create a custom class object that will expose some properties. I then want to bind some text boxes in the UI to those properties but I want to be able to do this for multiple instances of a class (Analog in my case). I am sure this is something simple but I am not understanding how to approach this.
Example of the class:
class Analog
{
public string LblA0
{ get; set; }
}
EDIT:
I have figured out how to bind to a class but I am unsure how I would create another class instance to bind to separately.
<Grid>
<Grid.DataContext>
<local:Analog/>
</Grid.DataContext>
<TextBlock x:Name="labelAnalog0"
Text="{Binding LblA0, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
Grid.Column="0" Grid.Row="2" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
EDIT 2: ViewModel class?
class ViewModel
{
public Analog Analog0
{ get; set; }
}
Okay thanks to Clemens I think I understand how to solve this.
Here are the classes I have made:
class Analog
{
public Analog(string s)
{
lblA = s;
}
private string lblA;
public string LblA
{
get
{
return lblA;
}
set
{
lblA = value;
}
}
}
class ViewModel
{
Analog analog0 = new Analog("test");
Analog analog1 = new Analog("test2");
public Analog Analog0
{
get
{
return analog0;
}
}
public Analog Analog1
{
get
{
return analog1;
}
}
}
XAML
<TextBlock x:Name="labelAnalog0"
Text="{Binding Analog0.LblA, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
Grid.Column="0" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock x:Name="labelAnalog1"
Text="{Binding Analog1.LblA, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
Grid.Column="0" Grid.Row="2" HorizontalAlignment="Center" VerticalAlignment="Center"/>
The call to change the datacontext in the mainpage
analogGrid.DataContext = new ViewModel();

XAML inconsistent binding

I have a custom UserControl called ReferencedItem. It should take a Guid called ItemId. It is implemented as such:
private static void OnItemIdChanged(DependencyObject dobj, DependencyPropertyChangedEventArgs dpArgs)
{
//Do something
}
public static readonly DependencyProperty ItemIdProperty = DependencyProperty.Register("ItemId", typeof(Guid?), typeof(ReferencedItem), new FrameworkPropertyMetadata(
// use an empty Guid as default value
Guid.Empty,
// tell the binding system that this property affects how the control gets rendered
FrameworkPropertyMetadataOptions.AffectsRender,
// run this callback when the property changes
OnItemIdChanged
));
public Guid? ItemId
{
get { return (Guid?)GetValue(ItemIdProperty); }
set { SetValue(ItemIdProperty, value); }
}
public ReferencedItem()
{
InitializeComponent();
ViewModel = new ReferencedItemCtrlViewModel();
DataContext = ViewModel;
}
The ItemsSource will be made up of Reference objects defined as:
public class Reference
{
public Guid Id { get; set; }
}
Now when binding this ReferencedItem the value is not set as intended. Here is the code I want to work, but does not bind as intended:
<ItemsControl x:Name="ReferenceStack" ItemsSource="{Binding References}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:ReferencedItem ItemId="{Binding Id}" Height="30" HorizontalAlignment="Stretch" VerticalAlignment="Top"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I have tried:
<local:ReferencedItem ItemId="128d48f0-f061-49fb-af49-b8e4ef891d03" Height="30" HorizontalAlignment="Stretch" VerticalAlignment="Top"/>
This works as expected, the OnItemIdChanged method is triggered.
<Label Content="{Binding Id}" HorizontalAlignment="Left" VerticalAlignment="Top" Height="30" Width="90"/>
This works as expected, a label is rendered with the Id.
Is there something I'm missing here? From what I can tell the data is available at bind time -- it just doesn't bind under the exact conditions I need it to :)
Thanks for any input!
EDIT:
Here is the code-behind for ReferencedItemList, the first block of XAML posted above:
public partial class ReferencedItemList : UserControl
{
protected ReferencedItemListCtrlViewModel ViewModel;
public ReferencedItemList()
{
InitializeComponent();
ViewModel = new ReferencedItemListCtrlViewModel();
DataContext = ViewModel;
}
public void Load(Guid id, string name)
{
ViewModel.Load(id, name);
//ReferenceStack.ItemsSource = ViewModel.References;
}
}
The commented line has been experimented with in place of the ItemsSource="{Binding References}" that was defined in the XAML.
I don't think I can successfully post the code for ReferencedItemListCtrlViewModel without going down a rabbit hole -- needless to say it has a property References of type ObservableCollection<Reference> where Reference is defined earlier in this post.
ReferencedItem.xaml:
<v:BaseUserControl.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</v:BaseUserControl.Resources>
<StackPanel Orientation="Horizontal">
<Image x:Name="LinkIcon" Visibility="{Binding HasReference, Converter={StaticResource BooleanToVisibilityConverter}}" ToolTip="View Referenced Item" Source="/Images/link.png" Height="18" MouseUp="LinkIcon_MouseUp"/>
<TextBlock x:Name="ReferencedObjectDesc" Text="{Binding ReferenceHierarchy}" FontStyle="Italic" VerticalAlignment="Center" />
</StackPanel>
I just wanted to post the answer (explanation) I came across.
The problem was changing the DataContext of my ReferencedItem user control in the constructor. The view would instantiate a ReferencedItem and alter the DataContext - so once it was time to bind I had already flipped the context from the intended Reference.
There are multiple ways to resolve the timing - all project dependent. Either avoid setting the DataContext all together, set it post binding, or change the context on other items as appropriate.
Much thanks to Sinatr, Andrew Stephens, and Mike Strobel for all mentioning this at one point or another -- just took me some time to actually reach it. I don't think there's a way to assign credit to a comment, but let me know if there is.

Binding Text to Textbox in HubSection

This question is similar to Windows Phone 8.1 Toggling the visibility of a TextBlock in a DataTemplate
and countless others, but none of these ideas are working. The Loaded event is never triggered after I add my Textblock to my datatemplate in my hub. The Visual Tree search is not finding my TextBlock.
I have tried a basic binding like this:
<HubSection Background="{StaticResource HubSectionBackgroundBrush}"
MaxWidth="{x:Bind DesiredHubSectionWidth, Mode=OneWay}"
Header="You have selected:" Padding="60"
>
<DataTemplate x:DataType="local:Scenario4">
<TextBlock TextWrapping="Wrap" Style="{StaticResource BasicTextStyle}" HorizontalAlignment="Left" Text="{Binding Item}"/>
</DataTemplate>
</HubSection>
with
public string Item { get; set; }
Item = makeText.Text;
But this doesn't work (Text on the Hub is always empty). From looking at previous posts and code I have come up with this xaml code using Dependency Properties:
<HubSection Background="{StaticResource HubSectionBackgroundBrush}"
MaxWidth="{x:Bind DesiredHubSectionWidth, Mode=OneWay}"
Header="You have selected:" Padding="60"
>
<DataTemplate x:DataType="local:Scenario4">
<TextBlock TextWrapping="Wrap" Style="{StaticResource BasicTextStyle}" HorizontalAlignment="Left" Text="{x:Bind DesiredSelectionText, Mode=OneWay}"/>
</DataTemplate>
</HubSection>
with this in the c#
private static DependencyProperty s_desiredHubSectionWidthProperty
= DependencyProperty.Register("DesiredHubSectionWidth", typeof(double), typeof(Scenario4), new PropertyMetadata(560.0));
private static DependencyProperty selectionText = DependencyProperty.Register("SelectionText", typeof(string), typeof(Scenario4), new PropertyMetadata("Nothing"));
public static DependencyProperty DesiredHubSectionWidthProperty
{
get { return s_desiredHubSectionWidthProperty; }
}
public static DependencyProperty DesiredSelectionTextProperty
{
get { return selectionText; }
}
public string DesiredSelectionText
{
get { return (string)GetValue(selectionText); }
set { SetValue(selectionText, value); }
}
public double DesiredHubSectionWidth
{
get { return (double)GetValue(s_desiredHubSectionWidthProperty); }
set { SetValue(s_desiredHubSectionWidthProperty, value); }
}
and I set the text with
DesiredSelectionText = makeText.Text;
The width binding works perfectly, but the text is not updating. What is the proper way to change Hub/DataTemplate Text at Runtime? Since the Hub is not even printing "Nothing", something must be really wrong.
As a last resort I am thinking I will just construct my own datatemplate and assign it at runtime, but the only code I can find for that is deprecated(uses FrameworkElementFactory).
I was trying to assign to the textblock in the OnNavigatedTo method which is called before the textblock's Loaded method. That's why my program was showing the textblock as null.
Turns out the link I posted is the solution, just for me, the textblock was loaded after the page was navigated to.

Databinding a class with boolean and text to XMAL

I submitted this accidently, I fixed it myself and wasn't going to submit after writing out the question. But have learnt from the comments, thanks!
I am trying to create a simple todo app in win8 and eventually want to hock it into ToDoIst API.
I have created a simple task class to try and get my head around the databinding however I just can not get it to do what I want to do. I have used listboxes and other basic form elements.
task.cs
class task
{
private string content;
private bool complete;
public string Content
{
get {return content;}
set { content = value; }
}
public bool Complete
{
get { return complete; }
set { complete = value; }
}
public task(string content)
{
Content = content;
Complete = false;
}
}
MainPage.xaml
And at the moment my XAML looks like this.
<GridView HorizontalAlignment="Left" Margin="482,190,0,0" VerticalAlignment="Top" Width="400" Height="500">
<ListView x:Name="LVtasks" HorizontalAlignment="Left" Height="500" VerticalAlignment="Top" Width="400" ItemsSource="{Binding}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Content}"/>
<RadioButton/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</GridView>
I have put in some dummy data, 4 elements and when I run it, it comes up with 4 boxes with radio buttons however no text (there is space for the text) I am not sure how I would bind the bool?
I can not see what I am doing wrong. If anyone could help and point me in the right direction, I have searched a fair amount of tutorials and just can not figure it out.
Your code looks a little strange, maybe this is what you want:
<ListView x:Name="LVtasks" HorizontalAlignment="Left" Height="500" VerticalAlignment="Top" Width="400" ItemsSource="{Binding ToDoItems}">
<ListView.ItemTemplate>
<DataTemplate>
<RadioButton GroupName="ToDos" Content="{Binding Content}" IsChecked="{Binding IsComplete}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Do you really want radiobuttons? I think you want Checkboxes, the difference is that when you use radiobuttons only one in a group can be 'checked'
I used this code behind to have a datacontext:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
ToDoItems = new ObservableCollection<TodoItem>(new List<TodoItem>
{
new TodoItem("Content1"),
new TodoItem("Content2")
});
this.DataContext = this;
}
public ObservableCollection<TodoItem> ToDoItems { get; set; }
}
I changed the name of task to ToDoItem Task is already a class in the framework and might cause confusion.
For the RadioButton IsChecked is the property to bind to a bool property:
<RadioButton IsChecked="{Binding Path=Complete}"/>
Your text is most likely not showing up because you haven't set up any change notifications and the binding is happening before you set the Content values. Using the INotifyPropertyChanged interface is the most common and usually the easiest way to do this.
Like John already mentioned you should really let the window containing your listview implement the INotifyPropertyChanged interface. And to set the data context of your window like Johan said. It is important that you call the propertychanged method in each setter of a property. It is also useful to use an ObservableCollection as ItemSource of your listview. Try to create an instance of ObservableCollection, create a property for it calling propertychanged method in its setter an set rhe ItemSource of your listview to the property. Do not forget to also call propertychanged whenever you add or remove items from the collection

Passing parameters to CollectionViews

I am attempting to write my first implementation of databinding in a WPF form.
I have got to the point where I can successfully retrieve data to populate my combobox with the required entries but am stuck on how I would go about populating a dependent ListView given the current selection of the Combobox.
To explain my problem better this is the current view backing my application.
class SchoolBookViewModel
{
public SchoolBookViewModel() { }
//Problem is here... How do I pass in the SelectedSchoolClassID?
public CollectionView ClassBookListEntries(Guid SelectedSchoolClassID)
{
return new CollectionView(SchoolQuoteList.GetSchoolClassQuoteListBySchoolClassID(SelectedSchoolClassID, 2011, "MyConnectionString"));
}
public CollectionView SchoolEntries
{
get
{
return new CollectionView(SchoolList.GetSchoolList("MyConnectionString"));
}
}
}
And this is the XAML
<StackPanel Height="449" HorizontalAlignment="Left" Margin="12,12,0,0" Name="stackPanel1" VerticalAlignment="Top" Width="650" DataContext="{Binding}">
<Label Content="School:" Height="28" Name="lblSchoolName" Width="651" />
<ComboBox Height="23" Name="cmbSchoolNames" Width="644" DisplayMemberPath="SchoolName" ItemsSource="{Binding Path=SchoolEntries}" SelectedValuePath="SelectedSchoolClassID" SelectionChanged="cmbSchoolNames_SelectionChanged" />
<Label Content="Class booklist:" Height="29" Name="label1" Width="651" />
<ListView Height="163" Name="lblClassBookList" Width="645" ItemsSource="{Binding Path=ClassBookListEntries}" DisplayMemberPath="QuoteReference" />
</StackPanel>
And in the Window_Loaded method I call
stackPanel1.DataContext = new Views.SchoolBookViewModel();
Am I even on the right track? Any guidance would be appreciated.
To get the ComboBox's selection back into the ViewModel you need a property to bind to one of its selection properties. You can also get rid of the explicit CollectionViews if you're not doing anything with them. By just binding to the collections directly, ICollectionView instances will be created and managed for you automatically. Try structuring your VM like this:
class SchoolBookViewModel : INotifyPropertyChanged
{
private SchoolList _selectedSchoolClass;
public SchoolList SelectedSchoolClass
{
get { return _selectedSchoolClass; }
set
{
_selectedSchoolClass = value;
ClassBookListEntries = SchoolQuoteList.GetSchoolClassQuoteListBySchoolClassID(_selectedSchoolClass.Id, 2011, "MyConnectionString");
NotifyPropertyChanged("SelectedSchoolClass");
}
}
private SchoolQuoteList _classBookListEntries;
public SchoolQuoteList ClassBookListEntries
{
get { return _classBookListEntries; }
set
{
_classBookListEntries = value;
NotifyPropertyChanged("ClassBookListEntries");
}
}
private SchoolList _schoolEntries;
public SchoolList SchoolEntries
{
get
{
if (_schoolEntries == null)
_schoolEntries = SchoolList.GetSchoolList("MyConnectionString");
return _schoolEntries;
}
}
...
}
In general it's better to not set explicit Width and Height values and instead let the layout system size elements for you. You can also get rid of the DataContext="{Binding}" - this is redundant as DataContext is inherited and {Binding} means the value of the DataContext itself. Here's the XAML cleaned up and bound to the new properties from above:
<StackPanel HorizontalAlignment="Left" Margin="12,12,0,0" x:Name="stackPanel1" VerticalAlignment="Top">
<Label Content="School:" x:Name="lblSchoolName" />
<ComboBox x:Name="cmbSchoolNames" DisplayMemberPath="SchoolName" ItemsSource="{Binding Path=SchoolEntries}"
SelectedItem="{Binding SelectedSchoolClass}" />
<Label Content="Class booklist:" x:Name="label1" />
<ListView x:Name="lblClassBookList" ItemsSource="{Binding Path=ClassBookListEntries}" DisplayMemberPath="QuoteReference" />
</StackPanel>

Categories

Resources