C
C#8mo ago
Mass

✅ Inconsistent accessibility: property type is less accessible than property.

Hey! I'm making a UWP app, but from my understanding this is universal to C#. I have 2 different UWP Pages, that are both a public sealed partial class. In one of them, namely MainPage, I have a list (ObservableCollection to be precise, but I've tried changing to a normal List and it gives the same error) This is said list: static ObservableCollection<CustomObject> MyList { get; } = new ObservableCollection<CustomObject>(); I want to access this in the second Page, let's just call it Page2. I try to call MainPage.MyList, but can't because of the lists protection level. So I change the list to be public, and now I have an inconsistent accessibility. I'm having a hard time understanding what the error means exactly, can someone clear things up for me? How am I supposed to access the property from Page2?
24 Replies
Hazel 🌊💃
Hazel 🌊💃8mo ago
That error indicates that you're exposing something that is less accessibile than the type throwing it. For example:
internal class Foo;
public class Bar : Foo;
internal class Foo;
public class Bar : Foo;
Here, Bar gets that error because Foo is internal but Bar is public while attempting to derive from Foo. The options to resolve this are: 1. Change the accessibility level of Bar to internal. 2. Change the accessibility level of Foo to public. A snippet to help visualize why this is important:
// visible inside the defining assembly only
internal class Foo;

// visible outside the defining assembly
public class Bar
{
// visible outside the defining assembly
// but foo is only available internally
// so error
public Foo GetFoo()
{
return new Foo();
}

// visible internally only
// so no error
internal Foo GetFoo()
{
return new Foo();
}
}
// visible inside the defining assembly only
internal class Foo;

// visible outside the defining assembly
public class Bar
{
// visible outside the defining assembly
// but foo is only available internally
// so error
public Foo GetFoo()
{
return new Foo();
}

// visible internally only
// so no error
internal Foo GetFoo()
{
return new Foo();
}
}
leowest
leowest8mo ago
I think the issue here is a bit deeper because it depends on the scope of the page as well ideally u want to either pass the data as a parameter to the next page or have an object in common that can hold that data and will have a longer licecycle im not as knowledge on the flow of UWP, but how are u obtaining the data you're adding to your ObservableCollection?
Mass
MassOP8mo ago
yup, turns out it was because my CustomObject class wasn't public :D thanks for the help guys!
leowest
leowest8mo ago
making a static object across pages from page a is not ideal thou. keep that in mind.
Mass
MassOP8mo ago
right tbh it might not need to be static anymore because I changed the code up this issue was (hopefully) the last hurdle in that change xD
leowest
leowest8mo ago
how do u fill the observable thou? would u mind sharing some informaiton
Mass
MassOP8mo ago
I read information from a CSV file (though not because I want to) it's basically like this:
FileOpenPicker fileOpenPicker = new FileOpenPicker();
fileOpenPicker.FileTypeFilter.Add(".csv");
StorageFile result = await fileOpenPicker.PickSingleFileAsync();
if (result == null) return;
string csvText = await FileIO.ReadTextAsync(result);
using (StringReader reader = new StringReader(csvText)) {
string line;
while ((line = reader.ReadLine()) != null) {
string[] cells = line.Split(',');
...
MyList.Add(new CustomObject(cells));
...
}
}
FileOpenPicker fileOpenPicker = new FileOpenPicker();
fileOpenPicker.FileTypeFilter.Add(".csv");
StorageFile result = await fileOpenPicker.PickSingleFileAsync();
if (result == null) return;
string csvText = await FileIO.ReadTextAsync(result);
using (StringReader reader = new StringReader(csvText)) {
string line;
while ((line = reader.ReadLine()) != null) {
string[] cells = line.Split(',');
...
MyList.Add(new CustomObject(cells));
...
}
}
leowest
leowest8mo ago
I see so you're trying to avoid having to do that again on the next page are u using MVVM?
Mass
MassOP8mo ago
assuming a <ListView> in UWP counts, then yes
leowest
leowest8mo ago
MVVM is a pattern when u have like say a file called Page.xaml and another called PageViewModel.cs that feeds information to it in very dumb down terms so I assume you're writing the code on the xaml.cs
Mass
MassOP8mo ago
yuup
leowest
leowest8mo ago
so one way u could do it
Frame.Navigate(typeof(OtherPage), MyList);
Frame.Navigate(typeof(OtherPage), MyList);
and on the other end u would do
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
MyList = new ObservableCollection<CustomObject>((List<CustomObject>)e.Parameter);
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
MyList = new ObservableCollection<CustomObject>((List<CustomObject>)e.Parameter);
}
Mass
MassOP8mo ago
:o
leowest
leowest8mo ago
not ideal but since you're doing code behind... I was going to show u the other alternative but I dont think you're using Dependency Injection right?, so it might go over your head with complexity
Mass
MassOP8mo ago
main problem I'm immediately running into trying to do that is that I actually have 3 different lists (I only mentioned one because the number was irrelevant to my problem) they have different custom objects (though they all inherit from the same abstract base class) but I'm not entirely sure how I'd pass all 3 lists as a single parameter in C# I'm not using it but I'm down to learn about it oh wait reading up on dependency injection, I do think I've used this before (at the very least in other languages), at least if it's just about passing through dependencies as a parameter in a constructor, I feel like that just happens naturally in OOP not sure how I'd do that for UWP pages though, since they're not really constructed as far as I know
leowest
leowest8mo ago
that's the concept I was referring to an actually library like Microsoft.DependencyInjection
Mass
MassOP8mo ago
at least not manually constructed
leowest
leowest8mo ago
which is a bit more complex that jus the concept of inverting the control
Mass
MassOP8mo ago
oh yeah no in that case, not using that gotta quickly throw laundry into the washing machine so I'll brb
leowest
leowest8mo ago
well u would have something like a FileService for example, it would be acessible by both pages i.e.:
private readonly FileService _fileService;
public Page1(FileService fileService)
{
_fileService = fileService;
IntializeComponent();
}
private readonly FileService _fileService;
public Page1(FileService fileService)
{
_fileService = fileService;
IntializeComponent();
}
and FileService would be something like say
public class FileService
{
public List<CustomObject>? LastQuery { get; set; }
public async List<CustomObject> GetFiles(string path)
{
if (string.IsNullOrEmpty(path)) return;
LastQuery = new List<CustomObject>();
string csvText = await FileIO.ReadTextAsync(result);
using var reader = new StringReader(csvText))
{
string line;
while ((line = reader.ReadLine()) != null) {
string[] cells = line.Split(',');
LastQuery.Add(new CustomObject(cells));
}
return LastQuery;
}
}
public class FileService
{
public List<CustomObject>? LastQuery { get; set; }
public async List<CustomObject> GetFiles(string path)
{
if (string.IsNullOrEmpty(path)) return;
LastQuery = new List<CustomObject>();
string csvText = await FileIO.ReadTextAsync(result);
using var reader = new StringReader(csvText))
{
string line;
while ((line = reader.ReadLine()) != null) {
string[] cells = line.Split(',');
LastQuery.Add(new CustomObject(cells));
}
return LastQuery;
}
}
This is just hypothetical code for the sake of showing an example... So when u move to Page2 for example u could just call _fileService.LastQuery to get the files without having to go thru the proccess of requesting the user to lookup everything again. and what actually fills the the Page1 constructor and the FileService is the DependencyInjeciton u would setup etc
var serviceCollection = new ServiceCollection();
serviceCollection.AddScoped<FileService>();
serviceCollection.AddSingleton<Page1>();
serviceCollection.AddSingleton<Page2>();
var serviceCollection = new ServiceCollection();
serviceCollection.AddScoped<FileService>();
serviceCollection.AddSingleton<Page1>();
serviceCollection.AddSingleton<Page2>();
etc this is just a broad example to give u an idea. that's why I said the page parameter is fine for the way your doing it
Mass
MassOP8mo ago
yeah that makes sense, thanks for all that info!
leowest
leowest8mo ago
https://github.com/jenius-apps/ambie/tree/main if u have time this app is done in UWP and uses mvvm and di its a very nice project to look into to
MODiX
MODiX8mo ago
Use the /close command to mark a forum thread as answered
Mass
MassOP8mo ago
thanks, will take a peek for sure!
Want results from more Discord servers?
Add your server